Skip to content

HackingLZ/psdecode

Repository files navigation

psdecode.net

Compiled .NET 8 PowerShell deobfuscator. Hosts the PowerShell engine directly to intercept execution layers from obfuscated/malicious scripts without needing pwsh installed.

Replaces the deobfuscate_ps.ps1 + psdecode shell wrapper with a single self-contained binary.

WARNING: This tool executes real malware. The sandbox intercepts most execution paths, but PowerShell is a full language runtime — novel techniques can bypass proxy functions. Even with Docker, always run this on a dedicated malware analysis VM or disposable host, never on a workstation with access to production networks, credentials, or sensitive data. Docker adds isolation but is not a security boundary against a determined adversary.

Docker (recommended)

# Build
docker build -t psdecode .

# Scan a file (no network, read-only, temp filesystem)
docker run --rm --network none --read-only --tmpfs /tmp \
  -v /path/to/samples:/samples:ro \
  -v /path/to/output:/output \
  psdecode -o /output /samples/malware.ps1

# JSON output
docker run --rm --network none --read-only --tmpfs /tmp \
  -v ./samples:/samples:ro \
  psdecode -j /samples/malware.ps1

# Pipe from stdin
cat malware.ps1 | docker run --rm -i --network none --read-only --tmpfs /tmp \
  psdecode -

Key Docker flags:

  • --network none — no network access, blocks reverse shells and C2 callbacks
  • --read-only — immutable root filesystem
  • --tmpfs /tmp — writable temp on tmpfs, destroyed when container exits
  • -v ...:ro — samples mounted read-only

Build (native)

Requires .NET 8 SDK.

# Debug build
dotnet build

# Self-contained single-file release (~50MB ELF)
dotnet publish -c Release
# Output: bin/Release/net8.0/linux-x64/publish/psdecode

Note: The runtimes/ directory from the publish output must sit alongside the binary for PowerShell module discovery.

Usage

psdecode [options] <script.ps1>
psdecode [options] -          # read from stdin

Options

Flag Description
-o <dir> Save layer files to directory (per-sample subfolders)
-R Write plain-text report to output dir (or <input>.report.txt)
-j JSON output
-q Quiet mode (final layer only)
-r Raw layer content (no truncation)
-b Show binary layer hex dumps
--tags MITRE ATT&CK tags only
-t <sec> Execution timeout (default: 30, max: 300)
-v Verbose diagnostics to stderr
--version Print version
-h Help

Examples

./psdecode sample.ps1
./psdecode -j sample.ps1 2>/dev/null | jq .
./psdecode -o ./output -R sample.ps1   # layers + report in ./output/sample/
./psdecode --tags sample.ps1
cat sample.ps1 | ./psdecode -

# Batch: process all samples, each gets its own subfolder in ./output/
for f in samples/*.ps1; do ./psdecode -o ./output -R "$f"; done

When using -o, each sample gets its own subfolder:

output/
├── malware1/
│   ├── layer_1.txt
│   ├── layer_1.meta.json
│   ├── layer_2.bin
│   ├── layer_2.bin.desc
│   ├── layer_2.meta.json
│   └── report.txt
├── malware2/
│   ├── ...

Sandboxing

The tool has multiple layers of containment:

Application-level (built-in):

  • Constrained InitialSessionState with dangerous commands removed
  • 45+ proxy functions intercepting execution, I/O, network, and registry at the PowerShell engine level
  • Custom PSHost that intercepts Read-Host, Get-Credential, and PromptForChoice — prevents hangs and captures credential harvesting
  • Assembly load hooks that detect .NET payloads loaded via [Reflection.Assembly]::Load()
  • Fake Windows filesystem (C: drive via PSDrive, env vars, PSVersionTable)
  • Execution timeout with async cancellation

OS-level (Docker):

  • Network namespace isolation (--network none)
  • Read-only root filesystem
  • Non-root container user
  • Ephemeral tmpfs for temp files
  • Resource limits via --memory and --cpus if needed

Architecture

psdecode.net/
├── Program.cs              CLI entry, arg parsing, output formatting
├── Sandbox.cs              Runspace setup, ISS config, script execution
├── SandboxPSHost.cs        Custom PSHost for Read-Host/Get-Credential interception
├── AssemblyLoadHook.cs     Captures reflective .NET assembly loading
├── Dockerfile              Docker build for isolated execution
├── psdecode.csproj         .NET 8 project, Microsoft.PowerShell.SDK 7.4.5
├── Hooks/
│   ├── CommandHooks.cs     IEX, Start-Process, Invoke-Command, LOLBins
│   ├── FileIOHooks.cs      Set-Content, Add-Content, Out-File, BITS, registry
│   ├── NetworkHooks.cs     WebClient (Download/Upload/Open), Invoke-WebRequest, COM stubs
│   ├── SecurityHooks.cs    ConvertTo-SecureString, Add-Type, Defender prefs
│   └── StubHooks.cs        WMI, Get-Process, services, Write-Host
├── Analysis/
│   ├── AstAnalyzer.cs      Pre-execution AST analysis (base64, hex, char[])
│   ├── LayerWriter.cs      Layer file output, dedup, 32-layer cap
│   ├── MitreTagging.cs     ~90 MITRE ATT&CK behavior rules
│   └── PostProcessor.cs    Binary artifact extraction from text layers
└── Environment/
    ├── FakeFileSystem.cs   Fake C: drive directory tree
    └── FakeEnvironment.cs  Env vars, PSVersionTable, PSDrive

How it works

  1. AST pre-analysis -- Parses the script AST to extract base64 strings, -EncodedCommand args, hex blobs, and [char] sequences before execution.

  2. Constrained runspace -- Creates an InitialSessionState with dangerous commands removed and 40+ proxy functions registered. Proxies intercept IEX, Start-Process, New-Object, file I/O, network calls, registry ops, and more.

  3. Execution -- Runs the script inside the sandboxed runspace with a custom PSHost and fake Windows environment. Interactive prompts are intercepted, assembly loads are monitored, and intercepted content is written as numbered layers.

  4. Post-processing -- Extracts binary artifacts from text layers, applies MITRE ATT&CK tags, collects file drops from the fake filesystem.

Related Research

Academic papers on PowerShell deobfuscation and malware detection. Most report strong numbers but never released code.

Papers Without Published Tools

Paper Venue Claimed Result
Detecting Malicious PowerShell using Deep Neural Networks (Hendler, Kels, Rubin — Microsoft) ACM AsiaCCS 2018 AUC ~0.99
AMSI-Based Detection using Contextual Embeddings (Hendler, Kels, Rubin — Microsoft) ACM AsiaCCS 2020 90% TPR, <0.1% FPR
PSDEM: A Feasible De-Obfuscation Method (Liu et al.) IEEE ISCC 2018 High FP, couldn't handle unknowns
MPSAutodetect (Alahmadi et al.) Computers & Security 2022 98% TPR, 0.6% FPR
AST2Vec: Robust Neural Code Representation (Miao et al.) SciSec 2023 97.76% accuracy
Power-ASTNN (Zhang et al.) Computers & Security 2025 98.87% accuracy, AUC >0.995
Transformer-Based Original Content Recovery (Dedek & Scherer) ICONIP 2022 92% full recovery, 100% ≥90% recovery
Sentence Transformer + Similarity Learning (Fu, Song, Ding, Alaca) ACM TOPS 2025 99.01–99.73% accuracy
Command-line Obfuscation Detection using Small LMs (Outrata, Polak, Kopp — Cisco) arXiv 2024 Precision 0.9996, Recall 0.9991
Static Detection via Word Embeddings (Mimura & Tajiri) Internet of Things 2021 F1 0.995
GCN-based Detection (Choi) MDPI Applied Sciences 2021 +8.2% improvement
Malicious PS Detection using Attention MDPI Electronics 2020 96.5% detection rate
AI-based Detection with Feature Optimizations (Song et al.) ETRI Journal 2021 98% detection

Papers That DID Release Code

Paper Venue Result Code
Li et al. — Semantic-Aware Deobfuscation ACM CCS 2019 93.2% similarity recovery GitHub
PowerPeeler ACM CCS 2024 95% deobfuscation correctness Gitee
PowerDrive DIMVA 2019 4,642 scripts analyzed GitHub
Invoke-Deobfuscation IEEE DSN 2022 46% obfuscation score reduction Gitee

About

Compiled .NET 8 PowerShell deobfuscation sandbox — hosts the PS engine to intercept malware execution

Topics

Resources

License

Stars

5 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors