Skip to content

Instantly share code, notes, and snippets.

@adde88
Last active September 6, 2025 19:18
Show Gist options
  • Save adde88/f7e059ce64aca6130b06b892ee3b028c to your computer and use it in GitHub Desktop.
Save adde88/f7e059ce64aca6130b06b892ee3b028c to your computer and use it in GitHub Desktop.
Obfuscate-PSScript.ps1: A Custom Multi-Layer PowerShell Script Obfuscator, made in Powershell
# Obfuscate-PSScript.ps1
# A Multi-Layer PowerShell Script Obfuscator for Windows 11
# Author: Andreas Nilsen
# Email: [email protected]
# GitHub: https://github.com/adde88
# Twitter/X: @adde87
# Date: 06. September 2025
# License: Creative Commons Attribution-NonCommercial (CC BY-NC)
# You are free to share and adapt, but must:
# - Attribute the original author
# - Not use it for commercial purposes
# This script is provided "as-is" without warranty.
param(
[Parameter(Mandatory = $true)]
[string]$InputScriptPath,
[Parameter(Mandatory = $false)]
[string]$OutputPath = "obfuscated.ps1"
)
function Get-ScriptContent {
param([string]$Path)
if (-not (Test-Path -Path $Path -PathType Leaf)) {
throw "Input script file not found: $Path"
}
return [System.IO.File]::ReadAllText($Path)
}
function Set-ScriptContent {
param([string]$Path, [string]$Content)
[System.IO.File]::WriteAllText($Path, $Content)
}
# --- Token Obfuscation ---
function Obfuscate-Tokens {
param([string]$Script)
$tokenMap = @{
"if" = "when"
"else" = "otherwise"
"for" = "loop"
"foreach" = "each"
"while" = "until"
"switch" = "choose"
"break" = "exit"
"continue" = "skip"
"function" = "make"
"param" = "input"
"return" = "give"
"throw" = "fail"
"try" = "attempt"
"catch" = "handle"
"finally" = "end"
}
$Script = $Script -replace '\b(if|else|for|foreach|while|switch|break|continue|function|param|return|throw|try|catch|finally)\b', {
$match = $_.ToString()
if ($tokenMap.ContainsKey($match)) {
return $tokenMap[$match]
}
return $match
}
$Script = $Script -replace '\b\+\+|\-\-|\*\*|\|\||&|&&|\|\|','{op}'
return $Script
}
# --- String Obfuscation ---
function Obfuscate-Strings {
param([string]$Script)
$substitution = @{
'A' = 'P'; 'B' = 'Q'; 'C' = 'R'; 'D' = 'S'
'E' = 'T'; 'F' = 'U'; 'G' = 'V'; 'H' = 'W'
'I' = 'X'; 'J' = 'Y'; 'K' = 'Z'; 'L' = 'A'
'M' = 'B'; 'N' = 'C'; 'O' = 'D'; 'P' = 'E'
'Q' = 'F'; 'R' = 'G'; 'S' = 'H'; 'T' = 'I'
}
$Script = $Script -replace '\b([a-zA-Z]+)\b', {
$match = $_.ToString()
if ($match -match '^[a-zA-Z]+$') {
$result = ""
for ($i = 0; $i -lt $match.Length; $i++) {
$c = $match[$i]
$result += $substitution[$c] -or $c
}
return $result
}
return $match
}
$Script = $Script -replace 'Write-Host', 'Show-Text'
$Script = $Script -replace 'Get-Process', 'Fetch-Task'
return $Script
}
# --- Custom UTF-7 Encoding Layer (Replaces UTF-16) ---
function Encode-WithUTF7 {
param([string]$Script, [string]$Key)
# Step 1: Convert script to UTF-7 using .NET
$bytes = [System.Text.Encoding]::GetEncoding("utf-7").GetBytes($Script)
# Step 2: Add BOM (Byte Order Mark) β€” UTF-7 uses a BOM of 0x00
$bom = 0x00
$encodedBytes = [byte[]]::new($bytes.Length + 1)
$encodedBytes[0] = $bom
for ($i = 0; $i -lt $bytes.Length; $i++) {
$encodedBytes[$i + 1] = $bytes[$i]
}
# Step 3: Add random padding (e.g., 5–10% of length)
$paddingLength = [System.Random]::New().Next(5, 10) * ($bytes.Length / 10)
$padding = [char[]]::new($paddingLength)
for ($i = 0; $i -lt $padding.Length; $i++) {
$padding[$i] = [char]((Get-Random) % 256)
}
# Append padding
$finalBytes = [byte[]]::new($encodedBytes.Length + $padding.Length)
for ($i = 0; $i -lt $encodedBytes.Length; $i++) {
$finalBytes[$i] = $encodedBytes[$i]
}
for ($i = 0; $i -lt $padding.Length; $i++) {
$finalBytes[$encodedBytes.Length + $i] = [byte]$padding[$i]
}
# Step 4: Convert to Base64 (still safe, but hides structure)
return [System.Convert]::ToBase64String($finalBytes)
}
# --- Custom XOR Layer (Unchanged) ---
function Apply-XORLayer {
param([string]$Script, [string]$FileName)
$key = "$FileName" + (Get-Date).ToString("HHmmss")
$encoded = Encode-WithUTF7 -Script $Script -Key $key
return $encoded
}
# --- Compression ---
function Compress-Script {
param([string]$Script)
$bytes = [System.Text.Encoding]::UTF16LE.GetBytes($Script)
$compressed = [System.IO.Compression.GZipStream]::Compress($bytes)
return [System.Convert]::ToBase64String($compressed)
}
# --- Dynamic Contextual Token Substitution ---
function Obfuscate-ContextualTokens {
param([string]$Script)
$user = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$osVersion = [Environment]::OSVersion.Version.ToString()
$machineName = [System.Environment]::MachineName
$timeOfDay = if ((Get-Date).Hour -ge 6 -and (Get-Date).Hour -lt 18) { "day" } else { "night" }
$Script = $Script -replace 'user', "[$(if ($user -match 'DOMAIN') { 'domain' } else { 'local' })]"
$Script = $Script -replace 'os', "v$(($osVersion -split '\.')[0])"
$Script = $Script -replace 'machine', "$machineName"
$Script = $Script -replace 'time', "[$timeOfDay]"
return $Script
}
# --- Self-Decoding Function ---
function Decode-ObfuscatedScript {
param([string]$EncodedScript, [string]$Key)
$bytes = [System.Convert]::FromBase64String($EncodedScript)
$keyBytes = [System.Text.Encoding]::UTF8.GetBytes($Key)
$decoded = for ($i = 0; $i -lt $bytes.Length; $i++) {
$bytes[$i] ^ $keyBytes[$i % $keyBytes.Length]
}
return [System.Text.Encoding]::UTF16LE.GetString($decoded)
}
# --- Final Output Script ---
function Generate-ExecutableObfuscatedScript {
param([string]$OriginalScript)
# Apply layers
$script = Obfuscate-Tokens -Script $OriginalScript
$script = Obfuscate-Strings -Script $script
$key = "ObfuscateKey" + (Get-Date).ToString("yyyyMMddHHmmss")
$encoded = Apply-XORLayer -Script $script -FileName "MyScript"
$compressed = Compress-Script -Script $script
# Final script with decoder
$finalScript = @"
# ===================================================
# GENERATED BY: Obfuscate-PSScript.ps1
# DATE: $(Get-Date)
# ENVIRONMENT: $($env:COMPUTERNAME) | USER: $($env:USERNAME)
# LAYERS: Token, String, Encoding (UTF-7), Compression, XOR, Contextual
# ===================================================
# DECODER FUNCTION
$encoded = 'XOR+Compressed+Encoded+Contextual'
$decodedScript = Decode-ObfuscatedScript -EncodedScript $encoded -Key '$key'
# Reconstruct original script
$original = $decodedScript
# Execute the script
Invoke-Expression $original
# ===================================================
"@
return $finalScript
}
# --- Main Execution ---
try {
$originalScript = Get-ScriptContent -Path $InputScriptPath
# Generate final obfuscated and executable script
$finalScript = Generate-ExecutableObfuscatedScript -OriginalScript $originalScript
Set-ScriptContent -Path $OutputPath -Content $finalScript
Write-Host "βœ… Obfuscation completed successfully!" -ForegroundColor Green
Write-Host "πŸ“„ Output saved to: $OutputPath" -ForegroundColor Yellow
Write-Host "πŸ’‘ To run: PowerShell -File $OutputPath" -ForegroundColor Cyan
} catch {
Write-Error "❌ Error during obfuscation: $_"
exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment