Sitemap

Obfuscate PowerShell Scripts Right Inside VS Code

6 min readSep 11, 2026

--

I write a lot of PowerShell. I also spend a big chunk of my life reverse engineering other people’s code, so I know exactly how little a plain .ps1 file protects you. If someone can open the file, they can read everything: your logic, your API keys, your clever little tricks, all of it sitting there in plain text.

So I did something about it. I built a Visual Studio Code extension for PowerShell Pro Obfuscator, and now you can obfuscate a script without ever leaving the editor. Right-click, hit Obfuscate, done.

Press enter or click to view image in full size
PowerShell Pro Obfuscator in VS Code

Let me show you what it does and why you might want it.

First, why bother obfuscating PowerShell at all?

Here’s the uncomfortable truth about scripts: they ship as source. There’s no compilation step to hide behind. You hand someone a .ps1 or drop a module on a machine, and you've effectively handed them the source code too.

That’s fine for a throwaway automation script. It’s not fine when:

  • You’ve got connection strings, tokens or license checks baked into the script.
  • You spent weeks on an algorithm you’d rather your competitors didn’t copy in an afternoon.
  • You’re shipping a commercial tool and “just open it in Notepad” is a real threat model.

PowerShell runs everywhere now — Windows, Linux, DevOps pipelines, endpoint management — and that reach is great until you realize how much of your intent is readable by anyone with file access. Obfuscation won’t make your code bulletproof (nothing does), but it raises the cost of poking around from “five minutes” to “why am I even doing this”.

Before and after

Nothing sells this better than seeing it. Here’s a boring little script:

function Get-Greeting {
param([string]$Name)
Write-Host "Hello World from $Name!"
}
Get-Greeting "PowerShell Pro Obfuscator"

And here’s a slice of what comes back after obfuscation (I’m trimming it, the real output is much, much longer):

$script:_HnJTskg = 0
$jwNTQ = 297 * 400 + 36
$x4e8bfda = [Math]::Abs($jwNTQ - 8074)
function gnJjzMCN3V8P {
param([int]$slot, [int]$salt, [int]$guard)
if (-not ((Get-Variable -Name _HnJTskg -Scope Script -ErrorAction SilentlyContinue).Value)) { return '' }
$d = @(46866, 46865)
$r = ''
for ($i = 0; $i -lt $d.Length; $i++) {
[long]$v = [long]$d[$i]
[long]$v = [long]$v - ([long]($salt + $slot))
if ([long]$v -ge 0 -and [long]$v -le 0xFFFF) { $r += [char][int][long]$v }
}
return $r
}
# ...and a lot more

Same behaviour. Completely different reading experience. Would you want to rebuild the original from that, especially without a copy sitting next to you? That’s kind of the point, and it’s also why the output resists modern AI reconstruction attempts a lot better than a simple find-and-replace obfuscator.

How it works in the editor

The extension only wakes up for PowerShell-compatible files: .ps1, .psm1, .psd1, .ps1xml, .pssc, .psrc, .cdxml. You won't see the command cluttering menus in your JavaScript projects.

Using it is about as simple as I could make it:

  1. Open a PowerShell script.
  2. Either hit the Command Palette (Ctrl+Shift+P / Cmd+Shift+P) and run Obfuscate, or just right-click - in the editor, on the tab, or in the Explorer - and pick Obfuscate (PowerShell Pro Obfuscator).
  3. The file content gets sent to the PowerShell Pro Obfuscator Web API.
  4. A new obfuscate.{original extension} file opens (so script.ps1 becomes obfuscate.ps1) and jumps to the front as the active tab.

There’s a keyboard shortcut too: Ctrl+Alt+O (Cmd+Alt+O on macOS). Muscle memory does the rest.

Get Bartosz Wójcik’s stories in your inbox

Join Medium for free to get updates from this writer.

One thing worth saying out loud: without an activation code the extension runs in Demo mode. That gives you variable renaming, string splitting and integer encryption, capped at 1000 characters. Enough to kick the tires. For the heavy stuff — the VM engine, anti-debugging, self-integrity checks — you plug in an activation code and the limits go away.

What’s actually happening under the hood

I’m a sucker for this part, so bear with me. Under the covers, the engine parses your PowerShell into an AST:

Press enter or click to view image in full size
PowerShell Pro Obfuscator pipeline

Then runs a pipeline of transforms you can turn on and off. A few of my favorites:

Polymorphic string encryption. Every string gets its own throwaway decryptor, and the algorithm shape is different every single run. No two builds look alike, which makes automated deobfuscation genuinely annoying.

A VM engine. Selected statements get lifted into a tiny virtual machine with shuffled opcodes and decoy instructions. Now an analyst has to reverse the interpreter first before they even get to your code. Fun.

Finite-state automata. Straight-line code gets rewritten into a state machine with opaque schedulers, so “read it top to bottom” stops working as a strategy.

Anti-debugging. Polymorphic probes watch for attached debuggers, breakpoints and tracing. Trip one and the script quietly exits instead of showing its hand.

Self-integrity checks. A bootstrap probe fingerprints the script on disk. Patch a byte and the string decryptors start spitting out garbage instead of plaintext. That’s the “self-defending” bit, and it’s my favorite way to punish casual tampering.

Protection linker. Honeypot functions, fake calls with random arguments, tripwires that only fire before startup finishes. Extracted snippets keep looking real to anyone reading them out of context.

You tune all of this from the extension’s Settings page. Same labels, same descriptions as the online tool, so nothing gets lost in translation.

A fair warning, and I mean this: obfuscation touches the shape of your code, and PowerShell has plenty of grammar corners and hosting quirks. Always run the obfuscated script in your real target environment before you ship it. I’d rather you test it than email me at 2 a.m.

Settings you’ll actually touch

There aren’t a hundred knobs to fiddle with. The ones that matter:

  • Activation code (API key) — leave it empty for Demo mode, paste it in to unlock everything.
  • Compress source code before it goes to the Web API, handy for big scripts.
  • Every individual obfuscation strategy, so you can trade protection against size and performance however you like.

If you’d rather not click through menus, the whole thing runs on a Web API with bindings for PHP, Python, JavaScript, PowerShell, C# and Rust — drop it straight into a build server or CI job.

Where it runs

The extension is on the Visual Studio Code Marketplace:

Using Cursor or another VS Code-compatible editor? It’s on Open VSX too:

And if you don’t feel like installing anything yet, there’s a browser version, a Windows GUI, a Linux CLI and the API — all linked from the product page.

Want a free activation code?

I do this for my other tools and I’ll do it here too. Write a blog post about PowerShell Pro Obfuscator, post about it on X with #powershell #obfuscator #obfuscation, report a real bug, or send me a genuinely good obfuscation idea with some sample code. If it's legit - bam, you get a free code. Just drop me an email with the details.

That’s it. Go protect your scripts, and let me know what breaks so I can make it better. Godspeed hackers :)

--

--

Developer behind PELock software protection system, author of reverse engineering articles.