{
	"id": "f7e46cce-a954-4d6f-a21d-9da5b7153e6a",
	"created_at": "2026-04-06T00:13:31.793886Z",
	"updated_at": "2026-04-10T03:24:30.297626Z",
	"deleted_at": null,
	"sha1_hash": "7430f25ac24bcf60c8cf343888093ae641dc5db6",
	"title": "The Evolution of Offensive PowerShell Invocation",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 45794,
	"plain_text": "The Evolution of Offensive PowerShell Invocation\r\nBy By Lee Christensen\r\nPublished: 2015-12-28 · Archived: 2026-04-05 21:34:58 UTC\r\nBy now, PowerShell should be in every offensive security person’s arsenal. There are a plethora\r\nof PowerShell projects now that penetration testers and red teams can use when testing Windows networks. For\r\nprivilege escalation, we have PowerUp. For Active Directory enumeration and exploitation, we have PowerView.\r\nWant to quickly run Mimkatz in memory on a remote box? Invoke-Mimikatz to the rescue. Need some creative\r\ncomm channels? No problem, PowerShell can help there too. We even have fully-featured remote access tools\r\nrunning written completely in PowerShell! And given Microsoft’s push to make everything administrable via\r\nPowerShell, I think it’s safe to say PowerShell isn’t going anywhere anytime soon.\r\nWeaponization of PowerShell begins by invoking a PowerShell script in some way. Traditionally, offensive people\r\nuse some combination of the following commands to execute PowerShell on a host:\r\nExecute a script directly: powershell.exe -ExecutionPolicy Bypass -File script.ps1\r\nExecute a script via the command line:\r\npowershell.exe -ExecutionPolicy Bypass -C \u003ccommand\u003e\r\npowershell.exe -ExecutionPolicy Bypass -EncodedCommand \u003cBase64 Encoded Command\u003e\r\nWhile these techniques work in most cases, skilled defenders can easily detect these methods through process\r\ncreation monitoring. There are a few ways to get around the need to spawn powershell.exe to execute your\r\nPowerShell. At its core, powershell.exe loads the System.Management.Automation assembly and uses the\r\nfunctions therein to invoke PowerShell commands. Likewise, you too can create your own C# application that\r\nreferences the Automation assembly and then uses the Automation assembly’s functions to execute your\r\nPowerShell (see SharpPick for a great example). This, however, requires you to upload a custom application to a\r\ntarget’s machine (an action which is not always ideal).\r\nTo get around this, earlier this year I developed UnmanagedPowerShell. UnmanagedPowerShell is a C++ project\r\nthat starts up the .NET framework and loads (in memory) a custom C# assembly that executes PowerShell. This is\r\nuseful because, assuming you already have some form of code execution on the box, then you can use this code to\r\ninject PowerShell into any process you’d like, eliminating the need to spawn powershell.exe. Public examples of\r\nthis can be seen in ReflectivePick and PowerShell Empire’s psinject command (which uses ReflectivePick\r\nunderneath).\r\nWhile UnmanagedPowerShell removed the need to initially start powershell.exe, it is not exactly ideal because it\r\nis single threaded and therefore cannot handle executing multiple PowerShell scripts at once. To get around this,\r\nyou could use PowerShell jobs, but those have the unfortunate side effect of executing each job in a new instance\r\nof powershell.exe. You could load up UnmanagedPowerShell/ReflectivePick each time you want to execute\r\nPowerShell, but this has the potential downsides of excessive network traffic and process injection. You could also\r\nsolve this by creating a new PowerShell runspace for each job. This may also lead to problems, however, due to\r\nhttps://web.archive.org/web/20190508170150/https://silentbreaksecurity.com/powershell-jobs-without-powershell-exe/\r\nPage 1 of 2\n\nPowerShell scripts in different runspaces trying to PInvoke the same functions (If you have multiple runspaces,\r\nthey all execute in the same app domain. Any PInvoke’d functions are bound to the AppDomain as a whole, not\r\njust in the current runspace).\r\nTo solve these problems, I developed the library PowerShellTasking. PowerShellTasking solves these problems by\r\nexecuting each new PowerShell script in a new AppDomain (an isolation mechanism in the .NET framework).\r\nEach PowerShell script runs in the background in its own AppDomain until completion (solving the single-threaded only problem), upon which the main thread receives any output and then unloads the AppDomain\r\n(preventing the PInvoke-ing problems). PowerShellTasking is compiled as a class library and anyone can\r\neasily use it by referencing the library in their own project (see the “Example” program in the GitHub project for\r\nan example). While PowerShellTasking will not prevent scripts that use PowerShell jobs from spawning\r\npowershell.exe, it does provide operators a safer way (from an opsec perspective) to execute multiple PowerShell\r\nscripts simultaneously on a host.\r\nHopefully this gives you a better idea of how PowerShell invocation has evolved over time and gives you some\r\ninsights into the challenges of PowerShell weaponization. For resources on how to detect and protect yourself\r\nfrom malicious PowerShell usage in your network, see Lee Holmes’s excellent blog post and DerbyCon talk.\r\nSource: https://web.archive.org/web/20190508170150/https://silentbreaksecurity.com/powershell-jobs-without-powershell-exe/\r\nhttps://web.archive.org/web/20190508170150/https://silentbreaksecurity.com/powershell-jobs-without-powershell-exe/\r\nPage 2 of 2",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://web.archive.org/web/20190508170150/https://silentbreaksecurity.com/powershell-jobs-without-powershell-exe/"
	],
	"report_names": [
		"powershell-jobs-without-powershell-exe"
	],
	"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
		},
		{
			"id": "aa73cd6a-868c-4ae4-a5b2-7cb2c5ad1e9d",
			"created_at": "2022-10-25T16:07:24.139848Z",
			"updated_at": "2026-04-10T02:00:04.878798Z",
			"deleted_at": null,
			"main_name": "Safe",
			"aliases": [],
			"source_name": "ETDA:Safe",
			"tools": [
				"DebugView",
				"LZ77",
				"OpenDoc",
				"SafeDisk",
				"TypeConfig",
				"UPXShell",
				"UsbDoc",
				"UsbExe"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434411,
	"ts_updated_at": 1775791470,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/7430f25ac24bcf60c8cf343888093ae641dc5db6.pdf",
		"text": "https://archive.orkl.eu/7430f25ac24bcf60c8cf343888093ae641dc5db6.txt",
		"img": "https://archive.orkl.eu/7430f25ac24bcf60c8cf343888093ae641dc5db6.jpg"
	}
}