{
	"id": "d0157c38-af30-418b-860a-8ead7202845b",
	"created_at": "2026-04-06T00:16:52.200334Z",
	"updated_at": "2026-04-10T03:36:22.17153Z",
	"deleted_at": null,
	"sha1_hash": "b97793ec0c0a5881496b4de29bb5a5d2fb222b6d",
	"title": "Hijacking DLLs in Windows",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 863456,
	"plain_text": "Hijacking DLLs in Windows\r\nBy @Wietze\r\nPublished: 2020-06-22 · Archived: 2026-04-05 18:06:59 UTC\r\nDLL Hijacking\r\nFirst of all, let’s get the definition out of the way. DLL hijacking is, in the broadest sense, tricking a\r\nlegitimate/trusted application into loading an arbitrary DLL. Terms such as DLL Search Order Hijacking, DLL\r\nLoad Order Hijacking, DLL Spoofing, DLL Injection and DLL Side-Loading are often -mistakenly- used to say the\r\nsame. At best such terms describe specific cases of DLL hijacking, but are often used interchangeably and\r\ntherefore incorrectly. As an umbrella term, DLL hijacking is more accurate, as DLL hijacking always involves a\r\nDLL taking over from a legitimate DLL.\r\nAttackers have been seen to use DLL hijacking in different ways and for different reasons. Motives include\r\nexecution (executing malicious code through a trusted executable may be less likely to set off alarm bells, and in\r\nsome cases even bypasses application whitelist features such as AppLocker [1]), obtaining persistence (if the\r\ntarget application is pre-installed and runs regularly, so will the malicious code) and privilege escalation (if the\r\ntarget application runs under elevated permissions, so will the malicious code).\r\nThere is a variety of approaches to choose from, with success depending on how the application is configured to\r\nload its required DLLs. Possible approaches include:\r\n1. DLL replacement: replace a legitimate DLL with an evil DLL. This can be combined with DLL Proxying\r\n[2], which ensures all functionality of the original DLL remains intact.\r\n2. DLL search order hijacking: DLLs specified by an application without a path are searched for in fixed\r\nlocations in a specific order [3]. Hijacking the search order takes place by putting the evil DLL in a\r\nlocation that is searched in before the actual DLL. This sometimes includes the working directory of the\r\ntarget application.\r\n3. Phantom DLL hijacking: drop an evil DLL in place of a missing/non-existing DLL that a legitimate\r\napplication tries to load [4].\r\n4. DLL redirection: change the location in which the DLL is searched for, e.g. by editing the %PATH%\r\nenvironment variable, or .exe.manifest / .exe.local files to include the folder containing the evil\r\nDLL [5, 6] .\r\n5. WinSxS DLL replacement: replace the legitimate DLL with the evil DLL in the relevant WinSxS folder\r\nof the targeted DLL. Often referred to as DLL side-loading [7].\r\n6. Relative path DLL Hijacking: copy (and optionally rename) the legitimate application to a user-writeable\r\nfolder, alongside the evil DLL. In the way this is used, it has similarities with (Signed) Binary Proxy\r\nExecution [8]. A variation of this is (somewhat oxymoronically called) ‘bring your own LOLbin’ [9] in\r\nwhich the legitimate application is brought with the evil DLL (rather than copied from the legitimate\r\nlocation on the victim’s machine).\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 1 of 7\n\nFinding vulnerable executables\r\nThe biggest challenge is to find a vulnerable executable that can be exploited under default user permissions.\r\nWhen targeting pre-installed system executables on Windows, that typically excludes the first option, whilst any\r\nfolders eligible in options 2 and 3 have to be user writeable, as should the the files and folder in options 4 and 5.\r\nThis is usually not the case.\r\nThat leaves us with option six, the weakest variant, which the remainder of this post will focus on. Although\r\nusually unsuitable to obtain persistence or privilege escalation, it is often seen in the wild. Take\r\nOceanLotus/APT32, who at the end of 2019 have been observed to use a legitimate rekeywiz.exe alongside a\r\nmalicious duser.dll [10, 11]. In this case, the malware embedded the legitimate software and dropped it to disk,\r\nadopting the ‘bring your own LOLbin’ approach (another way of achieving the same would have been to copy the\r\nlegitimate executable from the \\system32\\ folder, assuming the executable hasn’t been patched yet).\r\nTo prevent new versions of this technique to be successful, it is worthwhile identifying executables that are\r\nvulnerable to this kind of DLL hijacking. This will provide red teamers with new means for execution, but more\r\nimportantly, it will allow threat hunters and defenders to take appropriate measures to detect and prevent.\r\nApproach\r\nTo keep things focussed, let’s limit ourselves to the executables present by default in c:\\windows\\system32\\ . On\r\nthe tested Windows 10 v1909 instance, this comprised a total of 616 executables, or 613 if you only consider\r\nsigned applications.\r\nTo monitor which DLLs each process attempts to load, we’ll use the well-known Procmon [12] tool. The approach\r\ntaken is therefore: (1) copy trusted executable to a user-writable location; (2) run copied executable; (3) use\r\nProcmon to identify DLLs looked for in user writable location.\r\nProcmon capturing DLL queries by a copy of winsat.exe, located in c:\\users\\wietze\\downloads\\ .\r\nThis allows us to identify all DLLs queried by each application, which will be all potential hijackable DLL\r\ncandidates. But it does not automatically follow that all of these are also loaded (and therefore executed). The\r\nmost reliable way to find out which DLLs are properly loaded, is to compile our own version of the DLL, and\r\nmake it write to a unique file upon successfully loading. If we then repeat the above approach for all target\r\nexecutables and DLLs, it will result in a collection of files that tells us which DLLs are confirmed vulnerable to\r\nDLL hijacking.\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 2 of 7\n\nCompiling custom versions of existing DLLs is more challenging than it may sound, as a lot of executables will\r\nnot load such DLLs if procedures or entry points are missing. Tools such as DLL Export Viewer [13] can be used\r\nto enumerate all external function names and ordinals of the legitimate DLLs. Ensuring that our compiled DLL\r\nfollows the same format will maximise the chances of it being loaded successfully.\r\nSample C code for our own version of dxgi.dll, which showed up in the Procmon recording of winsat.exe.\r\nIn summary, the approach taken is:\r\nDefine target\r\nexecutables\r\nGenerate Procmon\r\nconfig files for target\r\nEXEs\r\nExecute target EXEs,\r\nmonitor with Procmon\r\nAnalyse result logs,\r\nidentify potentially\r\nvulnerable DLLs\r\nCompile custom version\r\nof identified DLLs\r\nExecute target EXEs\r\nalongside custom DLLs\r\nAnalyse results,\r\nidentify confirmed\r\nvulnerable DLLs\r\nPhase 1\r\nPhase 2\r\nThe full code with a more thorough, technical explanation can be found on GitHub [14].\r\nConfirmed DLL Hijack candidates\r\nThe following table lists all executables in c:\\windows\\system32 on Windows 10 v1909 that are vulnerable to\r\nthe ‘relative path DLL Hijack’ variant of DLL Hijacking. Next to each executable is one or more DLLs that can be\r\nhijacked, together with the procedures of that DLL that are called. As explained in the previous section, these are\r\nnot mere theoretical targets, these are tested and confirmed to be working. The list comprises 287 executables\r\nand 263 unique DLLs.\r\nUpdate (2025-03-01): the results of this research have been included in HijackLibs, which provides a more\r\ncomprehensive and up-to-date view of DLL Hijacking opportunities.\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 3 of 7\n\nSome caveats:\r\nThe test was performed by simply running each executable, without specifying any parameters and with no\r\nfurther user interaction. This explains why the well-documented xwizard.exe DLL hijack [15] is not\r\npresent in this list, because it requires two (arbitrary) arguments for it to work.\r\nSome applications come with a GUI, or some other visual element that gives away the binary was\r\nexecuted. This also includes error messages: required DLLs might be missing, and the hijacked DLL\r\nobviously lacks the original functionality. Attackers are less likely to target such applications for DLL\r\nhijacking purposes.\r\nDLLs of which the original version was written in C++ have not been taken into account.\r\nA CSV version of the full list can be found on GitHub [14].\r\nCombining with UAC bypass\r\nHaving found all these executables, at most this allows us to execute code through trusted programs. However, it\r\nis also possible to gain elevated rights if used in conjunction with UAC Bypass techniques.\r\nUser Account Control (UAC) [16] was introduced in Windows Vista as a security feature, asking users for\r\nconfirmation through a prompt before a process running under normal privileges is elevated to higher privileges.\r\nAfter users complained about getting flooded with UAC prompts when doing arbitrary tasks, Microsoft introduced\r\nauto elevation in Windows 7, which automatically elevates certain processes if they are located in trusted\r\ndirectories (such as c:\\windows\\system32 ).\r\nWith this in mind, you could try running arbitrary code with elevated privileges by using an executable that is\r\nmarked for auto elevation that is also vulnerable to DLL hijacking. There are about 35 of such executables, as can\r\nbe seen in the previous section. The problem to overcome is that of the trusted directory: both the auto-elevate\r\nexecutable and the custom DLL need to be located in a trusted directory, but none of theses are user writeable.\r\nThere is some excellent research about bypassing UAC out there - one of my favourite techniques is the mocking\r\nof trusted directories using trailing spaces [17]. I would recommend reading the full blog post, but it boils down to\r\nusers being able to create c:\\windows \\system32\\ (note the space after the first folder), and auto-elevate\r\nexecutables placed in this folder consider this a trusted location.\r\nIt is debatable whether this is a proper security vulnerability - Microsoft argue it is not [18], but it is at least a flaw,\r\ngiven that most (non-enterprise) Windows computers are using ‘administrator accounts’ by default.\r\nEither way, this provides us with an excellent means through which DLL hijacking can be made much more\r\npowerful. Note that folders with trailing spaces cannot be created through traditional means on Windows. You\r\ncould compile some lines of C to do this, as is done by the original researcher, but it turns out VBScript can\r\nactually do this for us too. The following proof-of-concept shows that with only a few lines of code you can get\r\nthis to work:\r\nSet oFSO = CreateObject(\"Scripting.FileSystemObject\")\r\nSet wshshell = wscript.createobject(\"WScript.Shell\")\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 4 of 7\n\n' Get target binary and payload\r\nWScript.StdOut.Write(\"System32 binary: \")\r\nstrBinary = WScript.StdIn.ReadLine()\r\nWScript.StdOut.Write(\"Path to your DLL: \")\r\nstrDLL = WScript.StdIn.ReadLine()\r\n' Create folders\r\nConst target = \"c:\\windows \\\"\r\ntarget_sys32 = (target \u0026 \"system32\\\")\r\ntarget_binary = (target_sys32 \u0026 strBinary)\r\nIf Not oFSO.FolderExists(target) Then oFSO.CreateFolder target End If\r\nIf Not oFSO.FolderExists(target_sys32) Then oFSO.CreateFolder target_sys32 End If\r\n' Copy legit binary and evil DLL\r\noFSO.CopyFile (\"c:\\windows\\system32\\\" \u0026 strBinary), target_binary\r\noFSO.CopyFile strDLL, target_sys32\r\n' Run, Forrest, Run!\r\nwshshell.Run(\"\"\"\" \u0026 target_binary \u0026 \"\"\"\")\r\n' Clean files\r\nWScript.StdOut.Write(\"Clean up? (press enter to continue)\")\r\nWScript.StdIn.ReadLine()\r\nwshshell.Run(\"powershell /c \"\"rm -r \"\"\"\"\\\\?\\\" \u0026 target \u0026 \"\"\"\"\"\"\"\") 'Deletion using VBScript is problematic, use\r\nThe screenshot below shows what execution of the script might look like.\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 5 of 7\n\nAn example showing an elevated prompt after a malicious dxgi.dll was loaded by a legitimate winsat.exe from a\r\nmocked trusted directory, without getting any UAC prompts.\r\nIn the table above, all executable/DLL combinations for which the auto elevation was successful are marked in the\r\nfirst column. With over 160 possible combinations, there are quite some options.\r\nPrevention and detection\r\nA simple way to prevent DLL hijacking from happening would be for applications to always use absolute paths\r\ninstead of relative ones. Although some applications (notably portable ones) will not always be able to do so,\r\napplications located in \\system32\\ and relying on DLLs in the same folder have no excuse for doing otherwise.\r\nThe better option, which only very few Windows executables seem to do, is to verify all DLLs before loading\r\nthem (e.g. by checking their signatures) - this would largely eliminate the problem.\r\nNevertheless, as we have seen, attackers will still be able to bring older versions of legitimate/trusted applications\r\nthat can be exploited. So even if every application starts checking their DLLs before loading them from now on,\r\nwe would still have to deal with this problem.\r\nLet’s therefore focus on detection. You could hunt for the creation or loading of any of the DLLs mentioned before\r\nfrom unexpected paths, particularly in temp locations such as %appdata% . After all, the name of the (legitimate)\r\napplication loading the DLLs can be changed, but the filenames of DLLs are always fixed. A sample Sigma rule\r\nfor this can be found here [19] - it successfully detects our DLL hijacking, although as you can see, it doesn’t scale\r\nvery well and is likely to be prone to false positives. You could take a more generic approach by looking for the\r\npresence of Microsoft-signed binaries in unexpected locations, of the loading of DLLs from unexpected locations\r\nby such Microsoft-signed binaries (regardless of location).\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 6 of 7\n\nFinally, the demonstrated UAC bypass technique can be detected easily and reliably by looking for any activity in\r\nthe /windows / folder, or in any folders ending in a space for that matter. As described before, Windows folders\r\nwith trailing spaces cannot be created through normal means and should therefore be rare, and always suspicious.\r\nSetting your UAC mode to ‘Always notify’, one level higher than the default, will prevent this and other similar\r\nUAC bypass techniques from succeeding.\r\nPosted on 2020-06-22\r\nSource: https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nhttps://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows"
	],
	"report_names": [
		"hijacking-dlls-in-windows"
	],
	"threat_actors": [
		{
			"id": "af509bbb-8d18-4903-a9bd-9e94099c6b30",
			"created_at": "2023-01-06T13:46:38.585525Z",
			"updated_at": "2026-04-10T02:00:03.030833Z",
			"deleted_at": null,
			"main_name": "APT32",
			"aliases": [
				"OceanLotus",
				"ATK17",
				"G0050",
				"APT-C-00",
				"APT-32",
				"Canvas Cyclone",
				"SeaLotus",
				"Ocean Buffalo",
				"OceanLotus Group",
				"Cobalt Kitty",
				"Sea Lotus",
				"APT 32",
				"POND LOACH",
				"TIN WOODLAWN",
				"Ocean Lotus"
			],
			"source_name": "MISPGALAXY:APT32",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "870f6f62-84f5-48ca-a18e-cf2902cd6924",
			"created_at": "2022-10-25T15:50:23.303818Z",
			"updated_at": "2026-04-10T02:00:05.301184Z",
			"deleted_at": null,
			"main_name": "APT32",
			"aliases": [
				"APT32",
				"SeaLotus",
				"OceanLotus",
				"APT-C-00",
				"Canvas Cyclone"
			],
			"source_name": "MITRE:APT32",
			"tools": [
				"Mimikatz",
				"ipconfig",
				"Kerrdown",
				"Cobalt Strike",
				"SOUNDBITE",
				"OSX_OCEANLOTUS.D",
				"KOMPROGO",
				"netsh",
				"RotaJakiro",
				"PHOREAL",
				"Arp",
				"Denis",
				"Goopy"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "5da6b5fd-1955-412a-81aa-069fb50b6e31",
			"created_at": "2025-08-07T02:03:25.116085Z",
			"updated_at": "2026-04-10T02:00:03.668978Z",
			"deleted_at": null,
			"main_name": "TIN WOODLAWN",
			"aliases": [
				"APT32 ",
				"Cobalt Kitty",
				"OceanLotus",
				"WOODLAWN "
			],
			"source_name": "Secureworks:TIN WOODLAWN",
			"tools": [
				"Cobalt Strike",
				"Denis",
				"Goopy",
				"JEShell",
				"KerrDown",
				"Mimikatz",
				"Ratsnif",
				"Remy",
				"Rizzo",
				"RolandRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "2439ad53-39cc-4fff-8fdf-4028d65803c0",
			"created_at": "2022-10-25T16:07:23.353204Z",
			"updated_at": "2026-04-10T02:00:04.55407Z",
			"deleted_at": null,
			"main_name": "APT 32",
			"aliases": [
				"APT 32",
				"APT-C-00",
				"APT-LY-100",
				"ATK 17",
				"G0050",
				"Lotus Bane",
				"Ocean Buffalo",
				"OceanLotus",
				"Operation Cobalt Kitty",
				"Operation PhantomLance",
				"Pond Loach",
				"SeaLotus",
				"SectorF01",
				"Tin Woodlawn"
			],
			"source_name": "ETDA:APT 32",
			"tools": [
				"Agentemis",
				"Android.Backdoor.736.origin",
				"AtNow",
				"Backdoor.MacOS.OCEANLOTUS.F",
				"BadCake",
				"CACTUSTORCH",
				"CamCapture Plugin",
				"CinaRAT",
				"Cobalt Strike",
				"CobaltStrike",
				"Cuegoe",
				"DKMC",
				"Denis",
				"Goopy",
				"HiddenLotus",
				"KOMPROGO",
				"KerrDown",
				"METALJACK",
				"MSFvenom",
				"Mimikatz",
				"Nishang",
				"OSX_OCEANLOTUS.D",
				"OceanLotus",
				"PHOREAL",
				"PWNDROID1",
				"PhantomLance",
				"PowerSploit",
				"Quasar RAT",
				"QuasarRAT",
				"RatSnif",
				"Remy",
				"Remy RAT",
				"Rizzo",
				"Roland",
				"Roland RAT",
				"SOUNDBITE",
				"Salgorea",
				"Splinter RAT",
				"Terracotta VPN",
				"Yggdrasil",
				"cobeacon",
				"denesRAT",
				"fingerprintjs2"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434612,
	"ts_updated_at": 1775792182,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b97793ec0c0a5881496b4de29bb5a5d2fb222b6d.pdf",
		"text": "https://archive.orkl.eu/b97793ec0c0a5881496b4de29bb5a5d2fb222b6d.txt",
		"img": "https://archive.orkl.eu/b97793ec0c0a5881496b4de29bb5a5d2fb222b6d.jpg"
	}
}