Skip to main content

PowerShell obfuscation through stacked junk logic, dead code, and variable chaos.

Project description

Invoke-Junkpile

Built to execute, not to be understood...

Invoke-Junkpile Banner

Overview

Invoke-Junkpile is a Python-based tool that takes clean PowerShell scripts and transforms them into an entropic mess of stacked polymorphic variables, junk code, and obfuscated logic through randomization. The generated code is designed to be obfuscated while not appearing obfuscated. Designed for stealth, this tool aims to evade static detection signatures, confuse reverse engineers, and wreak havoc on basic string-matching defenses and entropy checks. In the end, it outputs fully functional, heavily obfuscated PowerShell code.

This was tested on a wide range of PowerShell scripts which worked in 99% of cases (see limitations below). This includes very large and complex scripts and scripts containing assemblies.


Features

  • Base64 encoding: done prior to obfuscation to preserve functionality.
  • Obfuscated chunking: Script is split into chunks assigned to randomly named variables.
  • Chunk stacking: Variable groups are randomly joined (2–7 chunks per assignment).
  • Realistic junk variables: Looks like legit PowerShell, using believable cmdlets and parameters.
  • Dead code injection: Includes random try/catch, loops and dummy assignments throughout.
  • Random execution obfuscation: Obfuscated reconstruction and execution of the final payload.
  • Blend-in obfuscation: Random whitespace, variable names and syntax constructs enhance stealth.

Example Usage

python Invoke-Junkpile.py -f ./input.ps1 -o ./output_obfuscated.ps1

Or using an inline command:

python Invoke-Junkpile.py -c "Get-Process | Where-Object { $_.CPU -gt 100 }"

With debug output:

python Invoke-Junkpile.py -f ./input.ps1 -o ./obf.ps1 --debug

Output Example (Truncated)

${Get-ChildItem -ErrorAction SilentlyContinue -LogName Windows PowerShell && ($calran)} += @(${Get-NetAdapter -ArgumentList -InformationLevel Silent && ($ihnk)}

$Win32_count = 5

try { Remove-Item -Path "C:\temp\logfile_5.txt" -ErrorAction SilentlyContinue } catch { Start-Sleep -Seconds 6 }

${Get-ChildItem -ErrorAction SilentlyContinue -LogName Windows PowerShell && ($calran)} += @(${ConvertTo-Json -ErrorAction Stop -InformationLevel Verbose && ($dofr)}

try { Remove-Item -Path "C:\temp\logfile_2.txt" -ErrorAction SilentlyContinue } catch { Start-Sleep -Seconds 0 }

$backupcount = 7

$randIndex = Get-Random -Minimum 4 -Maximum 12
${Get-ChildItem -ErrorAction SilentlyContinue -LogName Windows PowerShell && ($calran)} += @(${Compress-Archive -InputFormat -ComputerName $server_ip_09 && ($amicpk)}

$set_scaler_62 = 097

$Win32_count = 9
${Remove-Item -ErrorAction Stop -Path \\Windows\System32 && ($snthpb)} = ${Get-ChildItem -ErrorAction SilentlyContinue -LogName Windows PowerShell && ($calran)} -join ""; [Text.Encoding]::('UTF8').('Ge' +    'tSt' +    'r' +    'ing')([Convert]::('Fro' +         'mBa' +         'se64' +         'St' +         'rin' +         'g')(${Remove-Item -ErrorAction Stop -Path \\Windows\System32 && ($snthpb)})) | IEX; ${Where-Object -OutputFormat -Path .\Temp && ($fon)} = 816
${Write-Warning -InputFormat -Uri docs.google.com/document/u/0/ && ($tdi)} = 13

try { $y = 9 } catch { $error }
${Restart-Service -Debug -Seconds 30 && ($iih)} = 798

Command-Line Arguments

Flag Description
-f, --file Path to the input PowerShell script
-c, --command Inline PowerShell command to obfuscate
-o, --output Path to save the obfuscated output
--debug Enables debug output for development

How It Works

Obfuscation Phase:

  1. Comment Stripping: All lines with # comments are removed.
  2. Base64 Encoding: The original PowerShell script is encoded as a single base64 string.
  3. Chunking: That string is split into randomized-sized segments.
  4. Variable Generation: Each chunk is assigned to a randomly named variable that mimics legit cmdlet/parameter combos.
  5. Stacking: Chunks are grouped (typically 2–7 per line) to create the illusion of standard logic flow.
  6. Final Array: The chunks are combined into an array and then joined into a single base64 string variable.
  7. Execution Line: The joined base64 is decoded back into the original script using a stealthy and obfuscated [Text.Encoding]::UTF8.GetString() expression, which is piped into IEX.

Execution Phase:

  1. PowerShell processes each fake variable assignment.
  2. Junk variables and dead code execute without effect.
  3. The final base64 string is reconstructed and decoded.
  4. The resulting original PowerShell code is executed via IEX.

This creates a layered illusion of complexity while keeping the actual behavior intact.


VirusTotal Comparison

The power of obfuscation—visualized. The sample used was the "Using Reflection" script found over at https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell

Original Script (Unobfuscated AMSI Bypass)
This sample was detected by numerous engines: c65416981ba34fbb9638e263585a4ad908705126da79bb8fc353fea90a6824a9

VirusTotal Detection - Original

Invoke-Junkpile Obfuscated Script
After running the same script through Invoke-Junkpile: 3b5602182826d17beeac8ebb204950f6fe4a85809c91e38bd5dff7e46e684167

VirusTotal Detection - Obfuscated

0 / 63 detections

Heavily obfuscated, yet still fully functional.


Limitations / Drawbacks

  • ❌ Does not currently support:
    • Scripts with very large inline binaries or images may not work properly (some did, some didn't)
    • Increases script size.

Use Cases

  • Testing SIEM detection logic
  • Evading static detection for red team scripts
  • Teaching or demonstrating PowerShell obfuscation techniques

Deobfuscation

If you know what to look for, it shouldn't be too bad if you allow the PowerShell interpreter to do most of the work for you.

  1. Identify the variable that gets invoked using PowerShell invoke expressions (iex). It will be near the bottom.
  2. Replace the invoke with Write-Host to print the contents of the variable.
  3. You'll get Base64 echoed upon script excution. Use your favorite command line utility or online utility such as Cyberchef to decode it.
  4. Profit!

To-do

More randomly generated obfuscation around the Base64 execution and invoke expression. More to come!


Disclaimer

This tool is intended for educational and research purposes only. Use responsibly and ethically.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

invoke_junkpile-1.0.2.tar.gz (9.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

invoke_junkpile-1.0.2-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

File details

Details for the file invoke_junkpile-1.0.2.tar.gz.

File metadata

  • Download URL: invoke_junkpile-1.0.2.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for invoke_junkpile-1.0.2.tar.gz
Algorithm Hash digest
SHA256 e14d75548899570fe5b41bf04f8f30f43411868afb2c345857ed3591b38dec04
MD5 ec6de68645e72f5c9dcfeebccb66a6de
BLAKE2b-256 0dc6405c9d23f4e298575f751d505c45a3538f187af825f2e6a0c1f38ff20ad2

See more details on using hashes here.

File details

Details for the file invoke_junkpile-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for invoke_junkpile-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 968e20d1116a31ff58a8b091301fbee8fed3a1de3c003c552d7013191010e789
MD5 ef3b08dcba1a870f9cd7ab2af82f9333
BLAKE2b-256 c7e67fc5a413f89543f40368a51a009938304d6f464e4d8dd56a7732acc05f18

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page