{
	"id": "1007c059-9d77-48d0-bf22-5b0039f864a7",
	"created_at": "2026-04-06T00:11:22.506668Z",
	"updated_at": "2026-04-10T03:23:51.516502Z",
	"deleted_at": null,
	"sha1_hash": "d75a48990edef6798677f5542c9d6a7ff6551070",
	"title": "Subvert CLR Process Listing With .NET Profilers",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 211804,
	"plain_text": "Subvert CLR Process Listing With .NET Profilers\r\nArchived: 2026-04-05 15:27:54 UTC\r\nI recently stumbled onto an interesting capability of the CLR.\r\n\"A profiler is a tool that monitors the execution of another application. A common language runtime (CLR)\r\nprofiler is a dynamic link library (DLL) that consists of functions that receive messages from, and send messages\r\nto, the CLR by using the profiling API. The profiler DLL is loaded by the CLR at run time.\"\r\nhttps://msdn.microsoft.com/en-us/library/bb384493(v=vs.110).aspx\r\nSo. whats the big deal, really?\r\nTurns out in .NET 4 allows for Registry-Free Profiler Startup and Attach.  This can lead to some unintended\r\nconsequences.\r\nhttps://msdn.microsoft.com/en-us/library/ee471451(v=vs.100).aspx\r\nIn order for this work, you need to set 3 environment variables.\r\nAgain from MSDN:\r\nStartup-Load Profilers\r\nA startup-load profiler is loaded when the application to be profiled starts. The profiler is registered\r\nthrough the value of the following environment variable:\r\nCOR_ENABLE_PROFILING=1\r\nStarting with the .NET Framework 4, you use either the COR_PROFILER or the\r\nCOR_PROFILER_PATH environment variable to specify the location of the profiler. (Only\r\nCOR_PROFILER is available in earlier versions of the .NET Framework.)\r\nCOR_PROFILER={CLSID of profiler}\r\nCOR_PROFILER_PATH=full path of the profiler DLL\r\nIf COR_PROFILER_PATH is not present, the common language runtime (CLR) uses the\r\nCLSID from COR_PROFILER to locate the profiler in the HKEY_CLASSES_ROOT of the\r\nregistry. If COR_PROFILER_PATH is present, the CLR uses its value to locate the profiler\r\nand skips registry lookup. (However, you still have to set COR_PROFILER, as discussed in\r\nthe following list of rules.)\r\nhttps://web.archive.org/web/20170720041203/http://subt0x10.blogspot.com/2017/05/subvert-clr-process-listing-with-net.html\r\nPage 1 of 3\n\nSo, if our objective is to hijack a .NET process, like say PowerShell, we don't really want a Profiler to load, we\r\njust want to be able to manipulate the process.  It turns out you can get a dll to load into the .NET process that is\r\nnot even a Profiler.  This was interesting to me.  The CLSID is just random for this purpose.\r\nSo, I had this idea, I could write quick POC DLL that hides a process from PowerShell.  Well, short story is this.\r\n If you load a Profiler, and don't properly setup the Profiler structures, then the .NET CLR will promptly eject your\r\ndll.\r\nFor details of how we hook and hide see this article.\r\nThats ok.  ;-)  So what I did was create a DLL that loads another DLL from memory, and then when my profiler\r\ngets evicted, my hooking dll will stay resident.  So the Profiler just becomes a bootstrap.\r\nThe result seen in this clip below.  We enumerate processes with Get-Process in a \"non-profiled\" PowerShell\r\nprocess.  We get the details just fine.  Then we set our environment variables, load our PowerShell process, and\r\nnow, the processes are not seen.\r\nVideo:\r\nEin Fehler ist aufgetreten.\r\nJavaScript kann nicht ausgeführt werden.\r\nWhy does this matter.  As PowerShell become the window through which many sysadmins poll and interrogate\r\nthe operating system.  By using attaching a malicious profiler, we can mold the output so to speak to be what we\r\nwant.\r\nThis was just a very basic example.  I leave it up to you to explore further capabilities of tampering with the\r\nCLR/.NET applications through profilers.\r\nHope that was helpful.\r\nThats all for today.\r\nhttps://web.archive.org/web/20170720041203/http://subt0x10.blogspot.com/2017/05/subvert-clr-process-listing-with-net.html\r\nPage 2 of 3\n\nCasey\r\n@subTee\r\nSource: https://web.archive.org/web/20170720041203/http://subt0x10.blogspot.com/2017/05/subvert-clr-process-listing-with-net.html\r\nhttps://web.archive.org/web/20170720041203/http://subt0x10.blogspot.com/2017/05/subvert-clr-process-listing-with-net.html\r\nPage 3 of 3",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://web.archive.org/web/20170720041203/http://subt0x10.blogspot.com/2017/05/subvert-clr-process-listing-with-net.html"
	],
	"report_names": [
		"subvert-clr-process-listing-with-net.html"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434282,
	"ts_updated_at": 1775791431,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/d75a48990edef6798677f5542c9d6a7ff6551070.pdf",
		"text": "https://archive.orkl.eu/d75a48990edef6798677f5542c9d6a7ff6551070.txt",
		"img": "https://archive.orkl.eu/d75a48990edef6798677f5542c9d6a7ff6551070.jpg"
	}
}