“I like PowerShell, I like it a lot!” So begins a technical write-up on the blog of the security firm SCRT, before the author gets down to the real agenda. PowerShell — Windows’ built-in command shell and scripting engine — comes bundled with security instrumentation: AMSI, the Antimalware Scan Interface; CLM, Constrained Language Mode; plus assorted logging. These exist so defenders can see and stop malicious scripts. The author jokes that all this safety equipment slows his scripts down, that there must be a “performance gain” in removing it. Reader, he is not talking about performance.
The project: build a full-blown PowerShell console using only native C/C++ code — and, while rummaging around in the engine room, do some “cleaning.” Running PowerShell without launching powershell.exe is a field researchers have been ploughing for a decade, the author concedes, so nothing here is groundbreaking. The existing tools, though, mostly tackle one or two security features at a time and are mostly written in C#. That last part is a problem, because Microsoft built AMSI into the .NET Framework itself from version 4.8 onward — meaning the very platform you’d use to dodge the antivirus scanner is also wired to it.
There are exceptions. Invisi-Shell is written in C/C++ and patches all the known security features, but it does so by registering a CLR Profiler DLL and hooking functions on the fly. The SCRT author wanted something more direct: pure native code, so that any function could be patched without dragging in an extra layer of potential AMSI detection. (He’d planned just to release the tool, he says; a teammate talked him into writing up the recipe.) It’s been a busy season for such recipes — other researchers have shown how a sleepy Windows telemetry task can be nudged into running the wrong PowerShell.
First question: how hard is it to start PowerShell from C? Trivial, it turns out — if you cheat. The essay opens with a one-line program that simply launches powershell.exe. “This project is advancing quickly!” the author writes, before confessing that he’s kidding.
The genuine trick was borrowed from bypass-clm, a proof-of-concept on GitHub that the author has used repeatedly to slip past Constrained Language Mode. It conjures a real PowerShell console by calling a .NET method named ConsoleShell.Start. Real is the operative word: you get auto-completion, command history, even a working CTRL+C — not an emulation, the actual console. There was just one catch. That code is C#, and C# was exactly what the author had sworn off.
Enter one of Windows’ stranger revolving doors. PowerShell runs on .NET, which produces “managed” code that must be interpreted by the Common Language Runtime, whereas C/C++ produces unmanaged code with no such needs. Managed applications calling down into unmanaged code — a feature called Platform Invoke — is everyday red-team tradecraft. The lesser-known fact, the author explains, is that the door swings both ways: Microsoft provides interfaces that let an unmanaged, native application host the CLR and execute managed code. It’s “a lot more convoluted, but it is doable,” and offensive tools have done it before — the post cites UnmanagedPowerShell, loadDotNetAssemblyFromMemory.cpp and BetterNetLoader.
So the plan is diplomacy by remote control: host the CLR inside a C/C++ program, then conduct the managed world from a safe distance. The ritual goes: summon the CLR, start version v4.0.30319 of the runtime, create an AppDomain, load the System.Management.Automation assembly, and start invoking methods. Two invocations, specifically. First, RunspaceConfiguration.Create() — polite enough to be static and to require no arguments. Second, ConsoleShell.Start(), which needs its luggage packed into a SAFEARRAY: the runspace configuration, a banner, and an optional list of arguments. All of it shuttled through the baroque data types of the Component Object Model — BSTR, VARIANT, SAFEARRAY — which are less variables than small administrative procedures with memory addresses.
It is slow, fiddly work for a result that, as the author cheerfully admits, already exists elsewhere. But that’s the red-team economy: the point isn’t a faster shell, it’s one the security stack doesn’t recognise as a shell. And should the whole enterprise seem like an enormous effort to avoid one scanner, remember the joke at the top — the one about performance. The fastest way to launch PowerShell from C remains that single line summoning powershell.exe into existence, beaming, visible to every security product on the machine. Stealth, like comedy, is mostly timing.

