I built ObfusPS as a research-oriented PowerShell obfuscation framework focused on one constraint above everything else:
Obfuscation must not change runtime behavior.
The project explores structural and encoding-based transformations while preserving deterministic execution and providing runtime validation.
This article explains the design principles behind the engine.
Core Design Principles
1️⃣ Behavioral Fidelity First
ObfusPS includes an optional validation system that:
Executes the original script
Executes the obfuscated script
Compares:
stdout
stderr
exit code
If validation fails, the engine can retry with progressively safer settings.
Across the internal test matrix (13 scripts × 5 levels × 10 profiles), all combinations passed validation at the time of writing.
The goal is reproducible transformation — not just visual obfuscation.
2️⃣ Clear Separation of Responsibilities
ObfusPS uses a multi-language architecture:
Component Role
Go Core engine (pipeline, packers, RNG, metrics, validation)
PowerShell Native AST parsing
C# (.NET 8) Optional AST fallback parser
Python GUI wrapper
Important architectural decision:
The Go engine never executes PowerShell.
It produces transformed text only.
Runtime behavior lives entirely in generated PowerShell stubs.
This simplifies auditing and makes the build reproducible.
Obfuscation Model
ObfusPS combines two layers:
🔹 Pipeline transforms (pre-packing)
Applied in a defined order:
Identifier renaming
String encoding (XOR or RC4)
String tokenization
Numeric expression encoding
Formatting jitter
Opaque predicates
Function reordering (safe shuffle)
Dead code injection
Optional anti-reverse checks
Each transform can be enabled manually or via profile.
🔹 Encoding levels (1–5)
Five wrapping strategies progressively increase structural complexity:
Unicode character reconstruction
Base64 wrapping
Base64 with intermediate variable indirection
GZip compression + Base64
GZip + XOR encryption + fragmentation + polymorphic template
Level 5 adds:
32-byte XOR key derived from a seeded LCG
Fragment shuffling (Fisher–Yates)
Optional integrity verification
Maximum fragment count is 256 (auto-scaled).
Smart Analysis
ObfusPS includes a static analysis phase with 22+ internal feature detectors.
It evaluates:
Dynamic invocation patterns
Module-related constructs
String complexity
Control-flow patterns
Script size and entropy
The engine produces:
A complexity score (0–100)
A recommended profile
Suggested flags
This allows either manual configuration or automatic selection.
Profiles & Determinism
There are 10 predefined profiles ranging from minimal transformation (safe) to maximum configuration (paranoid, redteam).
All explicit flags override profile defaults.
For reproducible builds:
-seed N
ensures deterministic randomness — important for CI/CD and controlled testing scenarios.
Metrics & Reporting
After transformation, ObfusPS reports:
Output size
Shannon entropy
Character diversity
Alphanumeric ratio
Size ratio (input vs output)
Line count
This allows quantitative comparison between strategies instead of relying on visual inspection.
Scope & Limits
Input encoding: UTF-8 only
Output encoding: UTF-8 with BOM
Max input size: 100 MB
Fragment limit (level 5): 256
The tool is intended for:
Research
Authorized red/blue team simulation
IP protection
It is not designed for unauthorized or malicious usage.
Why Go?
The engine is written in Go because it provides:
Single static binary
Zero runtime dependency
Cross-platform compilation
Deterministic execution model
Strong performance for text-heavy pipelines
The architecture is intentionally explicit and modular to support auditing and future AST-based improvements.
Closing Thoughts
Obfuscation is not just about hiding code.
It is about:
Controlled transformation
Deterministic randomness
Structural mutation
Runtime equivalence guarantees
ObfusPS is an engineering exercise in making those constraints coexist.
Repository:
https://github.com/BenzoXdev/ObfusPS

Top comments (0)